Input
Output
Sample Input
abcd aaaa ababab .
Sample Output
1 4 3
题意:
对于字符串S=x+x+x+...,x=“ ”一段字符,我们定义x为S的循环节,现在要找S做多由多少个循环节组成。即找最小循环节。
比如S="abababab",则“ab”“abab”都是S的循环节,但x=“ab”是最小的,满足答案ans=8/2=4是最大的。
思路:
kmp:
此题关键在于求出最长循环节的长度,假设一个字符串长度为n,循环节长度为m,一定n是m的倍数,根据KMP算法Next数组的含义,假设一个字符串是由K个子串组成的,则字符串最后一个字符的Next数值一定是K-1个子串的长度,所以只需求出Next[n]后n-Next[n]就是可能的最长循环节,但是如果n-Next[n]不能整除n,则一定原字符串无循环,所以最后模判定一下就行了。
后缀数组:
见下一个题。
KMP解决最小循环节:
例如
ababab next[6] = 4; 即
123456
ababab
ababab
1~4位 与3~6位是相同的
那么1,2位
就等于3、4位
3、4位就等于5、6位
……
所以 如果 能整除 也就循环到最后了;
如果不能整除 ,
就最后余下的几位不在循环内。
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<memory> using namespace std; const int maxn=1000010; char c[maxn]; int Next[maxn],L; void KMP() { Next[1]=0; for(int i=2,k=0;i<=L;i++) { while(k&&c[i]!=c[k+1]) k=Next[k]; if(c[i]==c[k+1]) k++; Next[i]=k; } } int main() { while(~scanf("%s",c+1)){ if(c[1]=='.') return 0; L=strlen(c+1); KMP(); if(L%(L-Next[L])==0) printf("%d\n",L/(L-Next[L])); else printf("1\n"); } }