Description
给你一个长度为 (n) 的长字符串,完美子串既是它的前缀也是它的后缀,求完美子串的个数且统计这些子串的在长字符串中出现的次数。
Solution
KMP 求出 next 数组,则 next 数组从最后一位开始跳几次到 1 就是个数
对于出现次数,设为 f[],则 f[next[i]]+=f[i] 转移即可,初始值 f[i]=1
#include <bits/stdc++.h>
using namespace std;
char s[1000005],p[1000005];
int n,m,fail[1000005],f[1000005];
int main()
{
ios::sync_with_stdio(false);
cin>>p+1;
n=strlen(s+1);
m=strlen(p+1); // Care for the order
// Build fail array for pattern string
for(int i=2; i<=m; i++)
{
fail[i]=fail[i-1];
while(p[fail[i]+1]-p[i] && fail[i]) fail[i]=fail[fail[i]];
if(p[fail[i]+1]==p[i]) ++fail[i];
}
fail[0]=-1;
for(int i=1,j=1; i<=n;)
{
if(s[i]==p[j])
{
if(j<m) ++i,++j;
else
{
cout<<i-m+1<<endl;
j=fail[j-1]+1;
}
}
else
{
j=fail[j-1]+1;
if(j<=0) j=1,i++;
}
}
int ans=0;
int p=m;
for(int i=m; i>=1; --i) f[i]++, f[fail[i]]+=f[i];
vector <int> o;
while(p) ++ans,o.push_back(p),p=fail[p];
reverse(o.begin(),o.end());
cout<<ans<<endl;
for(int i=1; i<=ans; i++)
{
cout<<o[i-1]<<" "<<f[o[i-1]]<<endl;
}
}