POJ 2752 Seek the Name, Seek the Fame (KMP)

题意

给定一个字符串S,求出某些子串的个数,这些子串既是S的前缀也是S的后缀。

思路

说白了就是前缀和后缀的对称嘛,一下子就联想到了next[]数组(或者叫失败指针……),而next[]数组只是求出长度最长的一个,先称为S*。随后我们递归地寻找(S*)*,((S*)*)*,这些都是符合的子串,直到S*……*长度为0. POJ 2752

代码

  [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]
原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114115.html