Input
Output
Sample Input
abcd
aaaa
ababab
.
Sample Output
1
4
3
Hint
大意:给出一个字符串 问它最多由多少相同的字串组成 (转载自https://www.cnblogs.com/zhanzhao/p/4761477.html)
如 abababab由4个ab组成
分析:
kmp中的next数组求最小循环节的应用
例如
ababab next[6] = 4; 即
ababab
ababab
1~4位 与2~6位是相同的
那么前两位
就等于3、4位
3、4位就等于5、6位
……
所以 如果 能整除 也就循环到最后了
如果不能整除
就最后余下的几位不在循环内
例如
1212121
1212121
最后剩余1不能等于循环节
#include<stdio.h>
#include<string.h>
char str[1000005];
int next[1000005];
int main ()
{
int i ,n;
while(scanf("%s" ,str)!=EOF && str[0] != '.')
{
//printf("WWW\n");
n = strlen(str);
int k = -1;
next[0] = -1;
for(i=1;i<n;i++)
{
//printf("%d %d\n",i,k);
while(k>-1&&str[k+1]!=str[i])
{
//printf("%d %c %c\n",k,str[k],str[i]);
k=next[k];
}
if(str[k+1]==str[i])
k++;
next[i]=k;
}
int t=next[n-1]+1;
if (n % (n-t)==0) printf("%d\n", n / (n-t));
else printf("%d\n", 1);
}
return 0;
}
此代码核心的另一种写法(大同小异)
int k = -1;
int j = 0;
next[0] = -1;
while(j<n)
{
//printf("%d %d\n",i,k);
if(k==-1||s[j] == s[k])
{
next[++j]=++k;
}
else
k=next[k];
}
我卡bug的代码
n = strlen(str); //这代码咋一看没有错误,但是仔细观察后会发现当输入数据为aabbaa时这个代码会卡死,原因是当i=2时
int k = 0;
next[0] = 0;
for(i=1;i<n;i++)
{
//printf("%d %d\n",i,k);
while(k>0&&str[k]!=str[i])//这个while语句会陷入死循环
{
//printf("%d %c %c\n",k,str[k],str[i]);
k=next[k];//k=next[k]=1,在这种情况下会一直执行这个while语句,睡完午觉后才突然发现。。。。,
}
if(str[k]==str[i])
k++;
next[i]=k;
}
总之,以后打代码不能总是只考虑到一种可能出错的方式,要看看自己的代码是否会卡在某些特殊数据上,如果遇到错误千万不能心急,首先要冷静下来,仔细看看自己的代码可能出错的地方,可能会发生错误的地方和数据,只有这样才能高效的找出问题的所在!!!