链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3374
题目大意:
给定一个字符串S, 可以通过向左移位得到另一个字符串。例如,S="SKYLONG", 通过位移得到的所有字符串(后面的数字表示rank,即第几个):
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
求出一个字符串经位移后的所有字符串中字典序最小和字典需最大的rank,以及他们出现的次数。
分析与总结:
经过分析,很快可以得到大概的思路:
1. 把S复制成2倍
2. 找出字典序最小和最大的字符串
3. 直接KMP求出他们的次数即可。
关键在于第二步。 第一次做时直接枚举,结果TLE了。势必要用一个效率更高的方法找到字典序最小和最大的字符串。
经过百度得知这个方法就是“最小最大表示法”。
资料:
【浅析“最小表示法”思想在字符串循环同构问题中的应用--03 周源】:1.论文
2.ppt
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1000005;
char S[MAXN*2];
char first[MAXN];
char last[MAXN];
int rank_first, rank_last;
int next[MAXN];
void getNext(char* S,int* next){
int n=strlen(S);
next[0]=next[1]=0;
for(int i=1; i<n; ++i){
int j=next[i];
if(j && S[i]!=S[j]) j=next[j];
next[i+1] = S[i]==S[j]?1+j:0;
}
}
int find(char* S,char* P,int* next){
getNext(P,next);
int n=strlen(S);
int m=strlen(P);
int j=0;
int cnt=0;
for(int i=0; i<n; ++i){
while(j && S[i]!=P[j]) j=next[j];
if(S[i] == P[j]) ++j;
if(j==m){
++cnt;
}
}
return cnt;
}
//最小表示法
void getMin(char* S){
int i=0, j=1;
int len=strlen(S);
len >>= 1;
while(i<len && j<len){
int k=0;
while(k<len && S[i+k]==S[j+k])
++k;
if(k >= len)
break;
if(S[i+k] > S[j+k])
i = max(i+k+1,j+1);
else
j = max(i+1,j+k+1);
}
int pos=min(i,j);
rank_first=pos+1;
for(int i=0; i<len; ++i)
first[i] = S[pos++];
first[len] = '\0';
}
//最大表示法
void getMax(char* S){
int i=0, j=1;
int len=strlen(S);
len >>= 1;
while(i<len && j<len){
int k=0;
while(k<len && S[i+k]==S[j+k])
++k;
if(k >= len)
break;
if(S[i+k] < S[j+k])
i = max(i+k+1,j+1);
else
j = max(i+1,j+k+1);
}
int pos=min(i,j);
rank_last=pos+1;
for(int i=0; i<len; ++i)
last[i] = S[pos++];
last[len] = '\0';
}
int main(){
while(scanf("%s",S)!=EOF){
int len=strlen(S);
for(int i=0; i<len; ++i){
S[len+i] = S[i];
}
S[2*len] = '\0';
// 先找到字典需最小的和最大的排位
getMin(S);
getMax(S);
printf("%d %d %d %d\n",rank_first,find(S+1,first,next),rank_last,find(S+1,last,next));
}
return 0;
}
—— 生命的意义,在于赋予它意义士。
原创http://blog.csdn.net/shuangde800,By
D_Double (转载请标明)
分享到:
相关推荐
HDU 1022 Train Problem I 附详细思路
hdu 1695 GCD(欧拉函数+容斥原理).docx
acm hdu as easy as a+b
本人准备2020年保研机试时刷的题目(虽然最后机试取消了,...来自某中流985,在HDU和vjudge平台上大概刷了400道。本文件地图(excel表格)包含了绝大部分我刷过的题目,笔记中具有思路、代码、总结和心得。 大佬勿入!
ACM题库,一些题目和答案,以及解题报告,传上来共享
Least Common Multiple ...先利用gcd算法求两个数的最大公约数,再考虑最小公倍数=两数乘积/最大公约数,即可求得最小公倍数。 注意:要考虑到输入的输入的n个数中的0,有0的要去掉0求其他数的最小公倍数。 代码:
HDU-1711 Number Sequence(KMP算法)For each test case, you should output one line wh
HDU的1250,主要是利用高精度加法,但是代码有点繁琐,效率不是很高
300+ AC 代码 。 大数 , 线段树 , 字符串 , dp.....
杭电ACMhdu1163
HDU1059的代码
hdu1001解题报告
杭电OnlineJudge 200-2099的解题报告
hdu 1574 passed sorce
HDU的一题........HDU DP动态规
B_(HDU_1231)(最大子段和,分治).cpp
hdu2101AC代码
hdu acm 教案 搜索入门 hdu acm 教案 搜索入门
搜索 dfs 解题代码 hdu1241
hdu 5007 Post Robot 字符串枚举。 暴力一下就可以了。