• 【后缀自动机例题】


    学习笔记戳这里: 折跃

    论文戳这里: 折跃

    论文中的例题

    SPOJ NSUBSTR - Substrings

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 2500010
    int N,a[MAXN],dp[MAXN],st[MAXN],Right[MAXN<<1],id[MAXN<<1];
    char s[MAXN];
    namespace SAM
    {
        int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1];
        int sz,last,root;
        inline void Init() {root=sz=last=1;}
        inline void Extend(int c)
        {
            int cur=++sz,p=last;
            len[cur]=len[p]+1;
            while (p && !son[p][c]) son[p][c]=cur,p=par[p];
            if (!p)    par[cur]=root;
            else 
                {
                    int q=son[p][c];
                    if (len[p]+1==len[q]) par[cur]=q;
                    else 
                        {
                            int nq=++sz;
                            memcpy(son[nq],son[q],sizeof(son[nq])); 
                            par[nq]=par[q]; len[nq]=len[p]+1;
                            while (p && son[p][c]==q)
                                son[p][c]=nq,p=par[p];
                            par[cur]=par[q]=nq;
                        }
                }
            last=cur;
        }
        inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(a[i]=s[i]-'a'+1);}
    }using namespace SAM;
    int main()
    {
        scanf("%s",s+1); N=strlen(s+1);
        SAM::Build();
        for (int i=1,now=root; i<=N; i++) now=son[now][a[i]],Right[now]++;
        for (int i=1; i<=sz; i++) st[len[i]]++;
        for (int i=1; i<=N; i++) st[i]+=st[i-1];
        for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
        for (int i=sz; i>=1; i--) Right[par[id[i]]]+=Right[id[i]];
        for (int i=1; i<=sz; i++) dp[len[i]]=max(dp[len[i]],Right[i]);
        for (int i=N; i>=1; i--) dp[i-1]=max(dp[i-1],dp[i]);
        for (int i=1; i<=N; i++) printf("%d
    ",dp[i]);
        return 0;
    } 
    View Code

    SPOJ SUBLEX - Lexicographical Substring Search

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define MAXN 900010
    char A[MAXN],ans[MAXN];
    int N,Q,K;
    namespace SAM
    {
        int son[MAXN<<1][27],par[MAXN<<1],len[MAXN<<1],root,last,sz;
        inline void Init() {root=sz=last=1;}
        inline void Extend(int c)
        {
            int cur=++sz,p=last;
            len[cur]=len[p]+1;
            while (p && !son[p][c]) son[p][c]=cur,p=par[p];
            if (!p) par[cur]=root;
            else
                {
                    int q=son[p][c];
                    if (len[p]+1==len[q]) par[cur]=q;
                    else
                        {
                            int nq=++sz;
                            memcpy(son[nq],son[q],sizeof(son[nq]));
     
                            len[nq]=len[p]+1;
                            par[nq]=par[q];
                            while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                            par[cur]=par[q]=nq;
                        }
                }
            last=cur;
        }
        inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]-'a'+1);}
        int st[MAXN],id[MAXN<<1],sum[MAXN<<1];
        inline void Pre()
        {
              for (int i=1; i<=sz; i++) st[len[i]]++;
            for (int i=1; i<=N; i++) st[i]+=st[i-1];
            for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
            for (int i=sz,Sum=0; i>=1; i--,Sum=0)
                {
                    for (int j=1; j<=26; j++)
                        Sum+=sum[son[id[i]][j]];
                    sum[id[i]]=Sum+1;
                }
        }
        inline void Query(int K)
        {
            int now=root,tot=0;
            while (K)
                {
                    for (int i=1; i<=26; i++)
                        if (son[now][i])
                            if (sum[son[now][i]]>=K)
                                {
                                    ans[++tot]='a'+i-1,K--,now=son[now][i];
                                    break;
                                }
                            else K-=sum[son[now][i]];
     
                }
            ans[++tot]=0;
        }
    }using namespace SAM;
    int main()
    {
        scanf("%s",A+1);
        N=strlen(A+1);
        SAM::Build();
        SAM::Pre();
        scanf("%d",&Q);
        while (Q--) scanf("%d",&K),Query(K),puts(ans+1);
        return 0;
    } 
    View Code

    SPOJ LCS - Longest Common Substring

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define MAXN 250010
    char A[MAXN],B[MAXN];
    int N,M;
    namespace SAM
    {
        int son[MAXN<<1][27],par[MAXN<<1],len[MAXN<<1],root,last,sz;
        inline void Init() {root=sz=last=1;}
        inline void Extend(int c)
        {
            int cur=++sz,p=last;
            len[cur]=len[p]+1;
            while (p && !son[p][c]) son[p][c]=cur,p=par[p];
            if (!p) par[cur]=root;
            else
                {
                    int q=son[p][c];
                    if (len[p]+1==len[q]) par[cur]=q;
                    else
                        {
                            int nq=++sz;
                            memcpy(son[nq],son[q],sizeof(son[nq]));
                            len[nq]=len[p]+1;
                            par[nq]=par[q];
                            while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                            par[cur]=par[q]=nq;
                        }
                }
            last=cur;
        }
        inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]-'a'+1);}
        inline int Query()
         {
             int now=root,Len=0,ans=0;
            for (int i=1; i<=M; i++)
                {
                    int c=B[i]-'a'+1;
                    if (son[now][c]) now=son[now][c],Len++;
                    else
                        {
                            while (now && !son[now][c]) now=par[now];
                            if (!now) now=root,Len=0;
                                else Len=len[now]+1,now=son[now][c];
                        }
                    ans=max(ans,Len);
                }
            return ans;
         }
    }using namespace SAM;
    int main()
    {
        scanf("%s%s",A+1,B+1);
        N=strlen(A+1),M=strlen(B+1);
        SAM::Build();
        printf("%d
    ",SAM::Query());
        return 0;
    } 
    View Code

    SPOJ LCS2 - Longest Common Substring II

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define MAXN 250010
    char A[MAXN],B[MAXN];
    int N,M;
    namespace SAM
    {
        int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1],mat[MAXN<<1],minn[MAXN<<1];
        int sz,root,last;
        inline void Init() {last=root=sz=1;}
        inline void Extend(int c)
        {
            int cur=++sz,p=last;
            len[cur]=len[p]+1;
            while (p && !son[p][c]) son[p][c]=cur,p=par[p];
            if (!p) par[cur]=root;
            else
                {
                    int q=son[p][c];
                    if (len[p]+1==len[q]) par[cur]=q;
                    else
                        {
                            int nq=++sz;
                            memcpy(son[nq],son[q],sizeof(son[nq]));
                            len[nq]=len[p]+1,par[nq]=par[q];
                            while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                            par[cur]=par[q]=nq;
                        }
                }
            last=cur;
        }
        inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]-'a'+1);}
        int st[MAXN],id[MAXN<<1];
        inline void Pre()
        {
            for (int i=1; i<=sz; i++) st[len[i]]++;
            for (int i=1; i<=N; i++) st[i]+=st[i-1];
            for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
            for (int i=1; i<=sz; i++) minn[i]=len[i];
        }
        inline void Match()
        {
            for (int i=1; i<=sz; i++) mat[i]=0;
            int now=root,Len=0;
            for (int i=1; i<=M; i++)
                {
                    int c=B[i]-'a'+1;
                    if (son[now][c])
                        now=son[now][c],Len++;
                    else
                        {
                            while (now && !son[now][c]) now=par[now];
                            if (!now) now=root,Len=0;
                                else Len=len[now]+1,now=son[now][c];
                        }
                    mat[now]=max(mat[now],Len);
                }
        }
        inline void Query()
        {
             for (int i=sz; i>=1; i--)
                {
                    int now=id[i];
                    minn[now]=min(minn[now],mat[now]);
                    if (par[now] && mat[now]) mat[par[now]]=len[par[now]];
                }
        }
    }
    int ans=0;
    int main()
    {
        scanf("%s",A+1); N=strlen(A+1);
        SAM::Build();
        SAM::Pre();
        while (~scanf("%s",B+1)) M=strlen(B+1),SAM::Match(),SAM::Query();
        for (int i=1; i<=SAM::sz; i++) ans=max(ans,SAM::minn[i]);
        printf("%d
    ",ans);
        return 0;
    } 
    View Code

    BZOJ SubString

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define MAXN 1200010
    char S[MAXN];
    int N,Q,M,ans,Mask;
    inline void read()
    {
        string str=S+1;
        int mask=Mask;
        for (int i=0; i<str.length(); i++)
            {
                mask=(mask*131+i)%str.length();
                swap(str[i],str[mask]);
            }
        for (int i=0,tot=0; i<str.length(); i++) S[++tot]=str[i];
    }
    namespace LCT
    {
        int fa[MAXN],ch[MAXN][2],val[MAXN],tag[MAXN];
        inline bool is_root(int x) {return !fa[x] || ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x;}
        inline void Add(int x,int v) {if (!x) return; val[x]+=v,tag[x]+=v;}
        inline void Pushdown(int x) {if (tag[x]) Add(ch[x][0],tag[x]),Add(ch[x][1],tag[x]),tag[x]=0;}
        inline void Rotate(int x)
        {
            int y=fa[x],w=ch[y][1]==x,z=fa[y];
            ch[y][w]=ch[x][w^1];
            if (ch[x][w^1]) fa[ch[x][w^1]]=y;
            if (ch[z][0]==y) ch[z][0]=x; else if (ch[z][1]==y) ch[z][1]=x;
            fa[x]=fa[y]; fa[y]=x; ch[x][w^1]=y;
        }
        int stack[MAXN];
        inline void Splay(int x)
        {
            int top=0,t=x,y; stack[++top]=x;
            while (!is_root(t)) stack[++top]=t=fa[t];
            while (top) Pushdown(stack[top--]);
            while (!is_root(x))
                {
                    y=fa[x];
                    if (!is_root(y))
                        if ((ch[fa[y]][0]==y)^(ch[y][0]==x)) Rotate(x);
                            else Rotate(y);
                    Rotate(x);
                }
        }
        inline void Access(int x) {for (int y=0; x; y=x,x=fa[x]) Splay(x),ch[x][1]=y;}
        inline void Link(int x,int y) {fa[x]=y; Access(y); Splay(y); Add(y,val[x]);}
        inline void Cut(int x) {Access(x); Splay(x); Add(ch[x][0],-val[x]); fa[ch[x][0]]=0,ch[x][0]=0;}
    }using namespace LCT;
    namespace SAM
    {
        int son[MAXN][27],len[MAXN],par[MAXN];
        int root,last,sz;
        inline void Init() {root=last=sz=1;}
        inline void Extend(int c)
        {
            int cur=++sz,p=last;
            len[cur]=len[p]+1; LCT::val[cur]=1;
            while (p && !son[p][c]) son[p][c]=cur,p=par[p];
            if (!p) par[cur]=root,LCT::Link(cur,root);
            else
                {
                    int q=son[p][c];
                    if (len[p]+1==len[q]) par[cur]=q,LCT::Link(cur,q);
                    else
                        {
                            int nq=++sz;
                            memcpy(son[nq],son[q],sizeof(son[nq]));
                            len[nq]=len[p]+1,par[nq]=par[q]; LCT::Link(nq,par[nq]);
                            while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                            par[cur]=par[q]=nq;
                            LCT::Cut(q); LCT::Link(cur,nq); LCT::Link(q,nq);
                        }
                }
            last=cur;
        }
        inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(S[i]-'A'+1);}
        inline void Insert()
        {
            read(); M=strlen(S+1);
            for (int i=1; i<=M; i++) Extend(S[i]-'A'+1);
        }
        inline int Query()
        {
            read(); M=strlen(S+1);
            int now=root;
            for (int i=1; i<=M; i++)
                if (!son[now][S[i]-'A'+1]) return 0;
                    else now=son[now][S[i]-'A'+1];
            LCT::Splay(now);
            return val[now];
        }
    }using namespace SAM;
    int main()
    {
        scanf("%d",&Q);
        scanf("%s",S+1); N=strlen(S+1);
        SAM::Build();
        while (Q--)
            {
                char opt[10];
                scanf("%s%s",opt+1,S+1);
                switch (opt[1])
                    {
                        case 'A' : SAM::Insert(); break;
                        case 'Q' : printf("%d
    ",ans=SAM::Query()); Mask^=ans; break;
                    }
    //            for (int i=1; i<=sz; i++) printf("%d %d %d %d
    ",i,ch[i][0],ch[i][1],val[i]);
            }
        return 0;
    }
    View Code

    BZOJ 工艺

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    using namespace std;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 600010
    int N,ans[MAXN],A[MAXN];
    namespace SAM
    {
        int len[MAXN<<1],par[MAXN<<1],last,root,sz;
        map<int,int>son[MAXN<<1];
        map<int,int>::iterator it;
        inline void Init() {last=root=sz=1;}
        inline void Extend(int c)
        {
            int cur=++sz,p=last;
            len[cur]=len[p]+1;
            while (p && !son[p][c]) son[p][c]=cur,p=par[p];
            if (!p) par[cur]=root;
            else
                {
                    int q=son[p][c];
                    if (len[p]+1==len[q]) par[cur]=q;
                    else
                        {
                            int nq=++sz;
                            son[nq]=son[q]; len[nq]=len[p]+1; par[nq]=par[q];
                            while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                            par[cur]=par[q]=nq;
                        }
                }
            last=cur;
        }
        inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]);}
        inline void Query()
        {
            int tot=0,now=root;
            while (tot!=(N>>1))
                {
                    it=son[now].begin();
                    now=it->second;
                    ans[++tot]=it->first;
                }
            printf("%d",ans[1]);
            for (int i=2; i<=tot; i++) printf(" %d",ans[i]); puts("");
        }
    }using namespace SAM;
    int main()
    {
        N=read();
        for (int i=1; i<=N; i++) A[i+N]=A[i]=read();
        N<<=1;
        SAM::Build();
        SAM::Query();
        return 0;
    }
    View Code
  • 相关阅读:
    MySQL主从复制与读写分离
    MySQL主从同步、读写分离配置步骤
    c# 无损压缩图片,接口传过来的是字节
    C# 和JAVA AES加密之间的互相兼容,C#版
    list的线程非安全性
    webrequesthelper
    .net core 实现微信登陆
    .net core 实现QQ登陆网站
    c# 深拷贝
    在H+框架下的一个给iframe 的body 添加事件。
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6202373.html
Copyright © 2020-2023  润新知