POJ2406 Power Strings
题目链接:https://vjudge.net/problem/POJ-2406
题目大意:
求一个字符串最多可以由多少个相同的子串组成。
知识点: KMP
解题思路:
利用 \(KMP\) 中 \(next[]\) 数组的性质:\(next[j]\) 表示字符串 \(S[0, ... , j-1]\) 的最长相同前后缀长度,也即 \(S[j-t, j-t+1, ... , j-1]\) 与 \(S[next[j]-t, next[j]-t+1, ... , next[j]-1]\) 相同,如图 \(1\) 所示。
当 \(\frac{j}{2} > next[j]\) 时,很明显字符串没有循环节,\(len \bmod (len - next[len]) \neq 0\),如图 \(2\) 的第 \(1\) 条线所示 ;
当 \(\frac{j}{2} \le next[j]\) 时,如果 \(len \bmod (len - next[len]) = 0\),那么图 2 中第三条线画圈的各段相同,而且整个字符串刚好有若干个如此的子段组成,因此答案即为 \(\frac{len}{len-next[len]}\),其中,第二条线所示的 \(len-next[len] = \frac{len}{2}\) 即为边界情况。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 7 using namespace std; 8 const int maxn=1e6+5; 9 10 char S[maxn]; 11 int len; 12 int Next[maxn]; 13 void GetNext() { 14 memset(Next, 0, sizeof(Next)); 15 int i = 0; 16 int j = -1; 17 Next[0] = -1; 18 19 while (i < len) { 20 if (j == -1 || S[i] == S[j]) { 21 i++, j++; 22 Next[i] = j; 23 } 24 else 25 j = Next[j]; 26 } 27 } 28 int main(){ 29 // freopen("in.txt","r",stdin); 30 while(scanf("%s",S)==1&&S[0]!='.'){ 31 len=strlen(S); 32 GetNext(); 33 if(len%(len-Next[len])==0) 34 printf("%d\n",len/(len-Next[len])); 35 else 36 printf("1\n"); 37 } 38 return 0; 39 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”