zoukankan      html  css  js  c++  java
  • CF452E Three strings 广义SAM

    题意:

    戳这里

    分析:

    一看多串匹配直接上广义 (SAM) ,每一个节点分别维护一下三个串的 (siz) 这样答案每一个点对答案的贡献就是 长度在 (len[link[x]])(len[x]) 之间每一个长度的匹配数都会加上 (siz[a]*siz[b]*siz[c])

    不过这里学到了一个小技巧,正确的在线构造的广义 (SAM) (即有两个特判的 (SAM)) 是可以基数排序得到拓扑序的,这样就不用 (DFS)

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
        const int maxn = 6e5+5;
        const long long mod = 1e9+7;
        int n[3];
        char ch[300005];
    
        struct suffix_automaton
        {
            int lst,tot;
            int trans[maxn][26],len[maxn],link[maxn],sa[maxn],cnt[maxn];
            long long ans[maxn],siz[maxn][3];
            suffix_automaton(){tot=lst=1;}
    
            void insert(int x,int id)
            {
                int tmp=lst;
                if(trans[tmp][x])
                {
                    int q=trans[tmp][x];
                    if(len[tmp]+1==len[q]) lst=q;
                    else
                    {
                        int clone=++tot;
                        link[clone]=link[q];
                        link[q]=clone;
                        len[clone]=len[tmp]+1;
                        for(int i=0;i<26;i++) trans[clone][i]=trans[q][i];
                        for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone;
                        lst=clone;
                    }
                    siz[lst][id]++;
                    return ;
                }
                int cur=++tot;lst=tot;siz[cur][id]++;
                len[cur]=len[tmp]+1;
                for(;tmp&&!trans[tmp][x];tmp=link[tmp]) trans[tmp][x]=cur;
                if(!tmp)
                {
                    link[cur]=1;
                }
                else
                {
                    int q=trans[tmp][x];
                    if(len[q]==len[tmp]+1)
                    {
                        link[cur]=q;
                    }
                    else
                    {
                        int clone=++tot;
                        len[clone]=len[tmp]+1;
                        link[clone]=link[q];
                        link[q]=link[cur]=clone;
                        for(int i=0;i<26;i++) trans[clone][i]=trans[q][i];
                        for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone;
                    }
                }
            }
        
            void sort()
            {
                for(int i=1;i<=tot;i++) cnt[len[i]]++;
                for(int i=1;i<=tot;i++) cnt[i]+=cnt[i-1];
                for(int i=1;i<=tot;i++) sa[cnt[len[i]]--]=i;
                for(int i=tot;i>=2;i--)
                {
                    int now=sa[i];
                    for(int j=0;j<3;j++) siz[link[now]][j]+=siz[now][j];
                    long long res=siz[now][0]*siz[now][1]*siz[now][2]%mod;
                    ans[len[link[now]]+1]=(ans[len[link[now]]+1]+res)%mod;
                    ans[len[now]+1]=(ans[len[now]+1]-res+mod)%mod;
                }
                for(int i=1;i<=tot;i++) ans[i]=(ans[i]+ans[i-1])%mod;
                for(int i=1,j=min(n[0],min(n[1],n[2]));i<=j;i++) printf("%lld ",ans[i]);
            }
    
        }sam;
        
        void work()
        {
            for(int i=0;i<3;i++)
            {
                scanf("%s",ch+1);n[i]=strlen(ch+1);sam.lst=1;
                for(int j=1;j<=n[i];j++) sam.insert(ch[j]-'a',i);
            }
            sam.sort();
        }
    }
    
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    7.4 List集合
    vue学习笔记
    javaWEB中web.xml配置文件相关
    maven常用dos命令
    Oracle,sqlserver,mySQl的区别和联系:
    oracle数据库视图,序列,索引的sql语句查看
    java 异常处理
    线程专题
    package、folder和source folder的区别
    Java内存分配之堆、栈和常量池
  • 原文地址:https://www.cnblogs.com/youth518/p/14221754.html
Copyright © 2011-2022 走看看