昨天把KMP复习了一下,顺便做了一些以前做过的题,貌似有那么点感觉O(∩_∩)O~
贴出来,方便以后复习,O(∩_∩)O~
http://poj.org/problem?id=1961
POJ 1961 Period
大意:
   定义字符串A,若A最多由n个相同字串s连接而成,则A=s^n,如"aaa" = "a"^3,"abab" = "ab"^2
   "ababa" = "ababa"^1
   
给出一个字符串A,求该字符串的所有前缀中有多少个前缀SA= s^n(n>1)
输出符合条件的前缀长度及其对应的n

  如aaa
  前缀aa的长度为2,由2个'a'组成
  前缀aaa的长度为3,由3个"a"组成

  分析:KMP
  若某一长度L的前缀符合上诉条件,则
    1.next[L]!=0(next[L]=0时字串为原串,不符合条件)
	2.L%(L-next[L])==0(此时字串的长度为L/next[L])

 对于2:有str[0]....str[next[L]-1]=str[L-next[L]-1]...str[L-1]
        =》str[L-next[L]-1] = str[L-next[L]-1+L-next[L]-1] = str[2*(L-next[L]-1)];
		假设S = L-next[L]-1;则有str[0]=str[s]=str[2*s]=str[3*s]...str[k*s],对于所有i%s==0,均有s[i]=s[0]
		同理,str[1]=str[s+1]=str[2*s+1]....
		      str[j]=str[s+j]=str[2*s+j]....
	    综上,若L%S==0,则可得L为str[0]...str[s-1]的相同字串组成,
		总长度为L,其中字串长度SL = s-0+1=L-next[L],循环次数为L/SL
        故对于所有大于1的前缀,只要其符合上述条件,即为答案之一

#include<stdio.h>
#include
<string.h>
const int N = 1000000+10;
char str[N];
int next[N];
int len;
void GetNext1(char str[N],int next[N])//寻找模式串的粗略next
{
int l=strlen(str);
next[
0]=-1;
int i=0,j=-1;
while(i<l)
{
if(j==-1||str[i]==str[j])
{
i
++;j++;
next[i]
=j;
}
else
j
=next[j];
}
}
int main()
{
int T = 0;
while(scanf("%d",&len)!=EOF)
{
T
++;
if(len == 0)break;
scanf(
"%s",str);
GetNext1(str,next);
int i;
printf(
"Test case #%d\n",T);
for(i=2;i<=len;i++)
{
if(next[i]!=0&&i%(i-next[i])==0)//保证不是原串且循环
{
printf(
"%d %d\n",i,i/(i-next[i]));
}
}

printf(
"\n");
}
return 0;
}

相关文章: