【题目大意】
寻找最小字典序循环串起始位置,和最大字典序循环串起始位置
并分别输出这个串在循环中所出现的次数。
【算法分析】
利用经典算法求出他们最小表示的位置。然后用KMP算出现了几次。
【其它】
1A。
好像挺慢的。。。
【CODE】
#include char s[2001111],p[1001111]; int minshow(){ int maxshow(){ void kmp(int st){ int main(){
int next[1001111],n;
int i=1,j=2,k=0;
while (i<=n && j<=n && k<=n){
if (s[i+k]==s[j+k]) k++;
else{
if (s[i+k]>s[j+k]) i+=k+1;
else j+=k+1;
if (i==j) i++;
k=0;
}
}
return i
int i=1,j=2,k=0;
while (i<=n && j<=n && k<=n){
if (s[i+k]==s[j+k]) k++;
else{
if (s[i+k]>s[j+k]) j+=k+1;
else i+=k+1;
if (i==j) i++;
k=0;
}
}
return i
int i,j,ans=0;
for (i=st,j=1;j<=n;i++,j++) p[j]=s[i];
next[1]=0; j=0;
for (i=2;i<=n;i++){
while (j && p[j+1]!=p[i]) j=next[j];
if (p[j+1]==p[i]) j++;
next[i]=j;
}
j=0;
for (i=1;i<=n+n-1;i++){
while (j && p[j+1]!=s[i]) j=next[j];
if (p[j+1]==s[i]) j++;
if (j==n){
ans++;
j=next[j];
}
}
printf("%d %d",st,ans);
}
while (scanf("%s",s+1)!=EOF){
n=strlen(s+1);
memcpy(s+n+1,s+1,sizeof(char)*n);
kmp(minshow()); printf(" ");
kmp(maxshow()); printf("n");
}
}
收藏了,学习下.
其实不需要kmp,最小串求一次next数组,然后len/(len-next[len])
回复fatboy_cw:Orz!!!!!!!!