[BZOJ3277]串

传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3277

广义后缀自动机上dp

建出广义后缀自动机之后直接跳parent树去更新就没了w

具体实现看代码吧

#include <bits/stdc++.h>
using namespace std;
string s[1000005];
int fa[1000005],tot=1,N,K,Len[1000005],Son[1000005][26],rt=1,las=1,vis[1000005],cnt[1000005],Sum[1000005];
void Insert(int x){
    int now=++tot,pre=las;
    las=now;
    Len[now]=Len[pre]+1;
    for (;pre&&!Son[pre][x];pre=fa[pre]) Son[pre][x]=now;
    if (!pre) fa[now]=rt;
    else{
        int q=Son[pre][x];
        if (Len[q]==Len[pre]+1) fa[now]=q;
        else{
            int nq=++tot;
            Len[nq]=Len[pre]+1;
            memcpy(Son[nq],Son[q],sizeof(Son[q]));
            fa[nq]=fa[q];
            fa[q]=fa[now]=nq;
            for(;pre&&Son[pre][x]==q; pre=fa[pre]) Son[pre][x]=nq;
        }
    }
}
void Times(){
    for (int i=1;i<=N;i++){
        int now=rt;
        for (int j=0;j<s[i].length();j++){
            now=Son[now][s[i][j]-'a'];
            int qwq=now;
            for (;qwq&&vis[qwq]!=i;) vis[qwq]=i,cnt[qwq]++,qwq=fa[qwq];
        }
    }
}
void dfs(int x){
    if (x==rt||vis[x]) return;
    vis[x]=1;
    dfs(fa[x]);
    Sum[x]+=Sum[fa[x]];
}
int main(){
    cin>>N>>K;
    for (int i=1;i<=N;i++)
        cin>>s[i];
    for (int i=1;i<=N;i++){
        las=1;
        for (int j=0;j<s[i].length();j++){
            Insert(s[i][j]-'a');
        }
    }
    Times();
    for (int i=1;i<=tot;i++) Sum[i]=(cnt[i]>=K)*(Len[i]-Len[fa[i]]);
    memset(vis,0,sizeof(vis));
    for (int i=1;i<=tot;i++)
        dfs(i);
    for (int i=1;i<=N;i++){
        int ans=0,now=rt;
            for (int j=0;j<s[i].length();j++)
                now=Son[now][s[i][j]-'a'],ans+=Sum[now];
        printf("%d ",ans);
    }
    return 0;
}

 

posted @ 2019-08-30 20:58  si_nian  阅读(174)  评论(0编辑  收藏  举报