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 mod (len - next[len]) eq 0),如图 (2) 的第 (1) 条线所示 ;

  当 (frac{j}{2} le next[j]) 时,如果 (len mod (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
",len/(len-Next[len]));
35         else
36             printf("1
");
37     }
38     return 0;
39 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
原文地址:https://www.cnblogs.com/Blogggggg/p/7821591.html