题意:输入一个字符串,问前缀和后缀相同的字符串长度以及这些字符串出现的次数
题解:
方法1:首先计算前缀和后缀相等的字符串,可以发现这就是KMP中next数组的定义while(next[t]) t = ne[t]可以找到所有满足条件的串
这时候只要算每个字符串出现的次数,设dp[i]为前缀在串中出现的次数,那么dp[next[i]] += dp[i]这里很好理解,每一个i都会对next[i]作出贡献,倒着dp,初始化为1
方法2:这道题也可以用后缀数组来做,后缀数组计算出height数组,那么只要计算所有后缀和整个串的最长公共前缀,等于后缀长度的就是满足条件的串
最后计算串出现的次数,可以在计算最长公共前缀的时候记录在数组,最后算一个后缀和就可以
这里用方法1
#include <bits/stdc++.h> #define maxn 101000 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; char s[maxn]; int ne[maxn], dp[maxn]; vector<pair<int ,int > >v; void kmp_init(char *x,int l,int *next){ int i = 0, j = next[0] = -1; while(i<l){ while(j!=-1&&x[i]!=x[j]) j = next[j]; next[++i] = ++j; } } int main(){ scanf("%s", s); int l = strlen(s); kmp_init(s, l, ne); for(int i=l;i>=1;i--){ dp[i]++; dp[ne[i]] += dp[i]; } for(int i=1;i<=l;i++) cout<<ne[i]<<" ";cout<<endl; int t = l; while(t){ v.push_back(make_pair(t, dp[t])); t = ne[t]; } sort(v.begin(), v.end()); cout<<v.size()<<endl; for(auto j:v) cout<<j.first<<" "<<j.second<<endl; return 0; }