题目链接:
http://poj.org/problem?id=2752
题目大意:
给定一个字符串S,计算出所有可能的前缀-后缀字符串的长度。前缀-后缀字符串指的是S的
子串不仅是S的前缀,还是S的后缀。比如S = "alala",前缀-后缀字符有{"a","ala","alala"}。
思路:
KMP算法的应用。在KMP算法中,当字符串匹配失败时,模式串的指针并没有指向0从头比
较,而是指向了一个特定的位置,因为这个Next[j]指向的位置pos前长度为Next[pos]的子
串,同模式串第j位前的长度为Next[j]的子串是相同的。
即S[0]~S[Next[len]]一定与S[len-1-Next[len]]~S[len-1]匹配。
为了找到既能做前缀又能做后缀的子串,那么可以找Next[len]前的长度为Next[len]的子串,
这个子串一定是前缀,又由Next函数的性质可知,这个前缀字符串长度和字符串长度为
Next[len]的后缀是相同的,这样就找到除S本身以外所有满足条件的子串。也可以找到所有
满足条件的子串长度。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 400010;
char str[MAXN];
int Next[MAXN],ans[MAXN],len;
void GetNext()
{
int i = 0,j = -1;
Next[0] = -1;
while(i < len)
{
if(j == -1 || str[i] == str[j])
{
i++,j++;
Next[i] = j;
}
else
j = Next[j];
}
}
int main()
{
while(cin >> str)
{
len = strlen(str);
GetNext();
ans[0] = len;
int id = 1,i = len;
while(Next[i] > 0)
{
ans[id++] = Next[i];
i = Next[i];
}
for(i = id-1; i >= 0; i--)
cout << ans[i] << ' ';
cout << endl;
}
return 0;
}