用kmp求最短循环节出现的次数,失配数组的妙用。
不想画图了~~
举个栗子,s = "ababab",则f[6] = 4,即s[1~4] == s[3~6],全写出来就是s[1] = s[3]. s[2] = s[4], s[3] = s[5], s[4] = s[6],然后就发现这些等式有关联的地方:化简一下,得到了:s[1] = s[3] = s[5], s[2] = s[4] = s[6],就是s[1~2] = s[3~4] = s[5~6],所以刚好把整个串都包含了,所以循环节就是2.
那也就是说,只要看(n - f[n])能否整除n,如果能的话,那这个循环节出现的次数就是n / (n - f[n]),否则循环节是s本身,输出1.
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e6 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), las = ' '; 25 while(!isdigit(ch)) las = ch, ch = getchar(); 26 while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar(); 27 if(las == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) putchar('-'), x = -x; 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 char s[maxn]; 38 int f[maxn], cnt = 0; 39 40 void init() 41 { 42 int m = strlen(s + 1); 43 for(int i = 2, j = 0; i <= m; ++i) 44 { 45 while(j && s[j + 1] != s[i]) j = f[j]; 46 if(s[j + 1] == s[i]) j++; 47 f[i] = j; 48 } 49 } 50 51 int main() 52 { 53 while(1) 54 { 55 scanf("%s", s + 1); 56 if(s[1] == '.') break; 57 init(); 58 int n = strlen(s + 1); 59 if(!(n % (n - f[n]))) write(n / (n - f[n])); 60 else write(1); 61 enter; 62 } 63 return 0; 64 }