一. 原题链接:http://poj.org/problem?id=2752
二. 题目大意:给一个字符串,让你找出所有子串中,既可以做前缀,也可以做后缀的。从小到大输出子串长度。
三. 解题思路:KMP的Next数组保存的是当前字符串前缀和后缀相同的最长的长度,但是,如果有更小的,那么它一定是那个最大的子串的子串,而且只要k = Next[k-1]就可以索引到其位置,然后再划归为更小的问题,直到Next[k]里面是0,表示没有前后缀相同了。
四,代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
const int MAX_N = 400100,
INF = 0x3f3f3f3f;
int Next[MAX_N];
char pattern[MAX_N];
void getNext()
{
int i, k;
Next[0] = 0;
for(i = 1; pattern[i]; i++){
k = Next[i-1];
while(pattern[i] != pattern[k] && k>0)
k = Next[k-1];
if(pattern[i] == pattern[k])
Next[i] = k+1;
else
Next[i] = 0;
}
}
void printRes()
{
stack <int> s;
int k, len = strlen(pattern);
s.push(len);
for(k = len-1; Next[k] > 0; k = Next[k-1])
s.push(Next[k]);
while(!s.empty()){
int t = s.top();
s.pop();
printf("%d ", t);
}
printf("\n");
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%s", pattern)){
getNext();
printRes();
}
return 0;
}