[CF432D] Prefixes and Suffixes

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;
    }
}

原文地址:https://www.cnblogs.com/mollnn/p/13232610.html