题意
给定一个字符串S,求出某些子串的个数,这些子串既是S的前缀也是S的后缀。
思路
说白了就是前缀和后缀的对称嘛,一下子就联想到了next[]数组(或者叫失败指针……),而next[]数组只是求出长度最长的一个,先称为S*。随后我们递归地寻找(S*)*,((S*)*)*,这些都是符合的子串,直到S*
……*长度为0.
代码
[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, end) for (int i = begin; i <= end; i ++)
using namespace std;
vector <int> ans;
int next[400005];
char s[400005];
void solve(){
int len = strlen(s), j = -1;
next[0] = -1;
for (int i = 1; i < len; i ++){
while(j > -1 && s[i] != s[j+1]) j = next[j];
if (s[i] == s[j+1]) j ++;
next[i] = j;
}
while(j > -1){
ans.push_back(j+1);
j = next[j];
}
ans.push_back(len-(j+1));
}
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
while(scanf("%s", s) != EOF){
ans.clear();
solve();
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size() - 1; i ++)
printf("%d ", ans[i]);
printf("%d
", ans[ans.size()-1]);
}
return 0;
}
[/cpp]