这题的话是next数组的性质来做的,假设next[len],它表示的意思就是对于len之前,总共有几个重复的。
既然是重复的,那就可以把前面重复的删掉,然后后面的就是完全不重复的一节,然后它就是最短循环节。
具体图示在这篇博客里面:https://www.cnblogs.com/xyqxyq/p/10397187.html
我们知道,如果next[len]此时为0,说明之前没有任何重复,所以它的循环次数就是1,要么我们就输出
len/(len-next[len]).
这个思路的问题在哪?假设我们有abcdab,这时候,我们知道next[len]不为0,然后我们就认为它是循环的,
然后我们就用公式输出了一个错误的答案。
正确的思路是,我们可以先用公式判断,即len%(len-next[len])==0,如果为真,说明有循环节,否则我们就输出1。
#include <cstdio> #include <cstring> const int maxn=1000005; char s[maxn]; int next[maxn]; void getnext() { next[0]=-1; int j=0,k=-1; int len=strlen(s); while (j<=len) { if (k==-1||s[j]==s[k]) next[++j]=++k; else k=next[k]; } } int main() { while (scanf("%s",s)&&s[0]!='.') { getnext(); int len=strlen(s); if (len%(len-next[len])==0) printf("%d ",len/(len-next[len])); else printf("1 "); } return 0; }