好吧,这其实是一道水题,只不过带着一个性质而已。
也就是是KMP求最小循环节。
先给出式子:len=n-(fail[n-1]+1)(针对从0开始,fail保存某个字符前缀最长公共前后缀的情况)
我的理解是,n=fail[n-1]+len',fail保存的是公共前后缀,因此len'中不会包含残缺的部分,假若len'中包含两个或以上最小循环节,就一定会被加入到fail中去,因为他保存最长公共前后缀。
1 #include<cstdio> 2 #include<cstring> 3 const int maxn=1e6+5; 4 int n,fail[maxn]; 5 char s[maxn]; 6 void getfail() { 7 fail[0]=fail[1]=0; 8 for(int i=1;i<n;++i) { 9 int j=fail[i]; 10 while(j&&s[j]!=s[i]) j=fail[j]; 11 fail[i+1]=s[j]==s[i]?j+1:0; 12 } 13 } 14 int main() { 15 scanf("%d%s",&n,s); 16 getfail(); 17 printf("%d",n-(fail[n-1]+1)); 18 return 0; 19 }