Seek the Name, Seek the Fame POJ - 2752 (KMP)
题意:给出一个字符串,问字符串中存在多少子串,使得这些子串既是字符串的前缀,又是字符串的后缀,要求从小到大依次输出这些子串的长度。
思路:根据 next 数组的定义,可以得到前缀 next[len] 长度的子串与后缀 next[len] 长度的子串相同,因此求出 len 处的 next 值,然后向下递归即可得到答案
next数组:next[i]表示以i为终点的前缀的最长相同前后缀长度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 4e5 + 10; 7 char s[maxn]; 8 int l; 9 int nxt[maxn]; 10 int ans[maxn]; 11 void work() { 12 for (int i = 2, j = 0; i <= l; i++) { 13 while (j > 0 && s[i] != s[j + 1]) 14 j = nxt[j]; 15 if (s[i] == s[j + 1]) j++; 16 nxt[i] = j; 17 } 18 } 19 20 21 22 int main() { 23 //freopen("in","r",stdin); 24 while(scanf("%s", s + 1)!=EOF) { 25 l = strlen(s + 1); 26 work(); 27 // for(int i = 1; i <= l; i++) 28 // cout << nxt[i] << " "; 29 int i = l; 30 int c = 0; 31 while(i){ 32 ans[c++] = nxt[i]; 33 i = nxt[i]; 34 } 35 for(int i = c - 2; i >= 0; i--) 36 printf("%d ",ans[i]); 37 printf("%d\n",l); 38 } 39 return 0; 40 }