• 【sam复习】用sam实现后缀排序


    没错,一定是无聊到一定境界的人才能干出这种事情。

    这个无聊的zcysky已经不满足于用后缀平衡树求sa了,他想用sam试试。

    我们回顾下sam的插入过程,如果我们从最后一个state沿着suffix link向上爬parent tree

    那么我们就可以遍历这个sam的所有后缀。

    那么我们把插入的时候经历的state全都标记下来,并且记录下这个state对应的序号

    在对parent tree进行dfs的时候先序遍历一下就可以了。

    #include<bits/stdc++.h>
    #define N 300010
    using namespace std;
    int n,c[N],tot,tota,sacnt,top=0,cnt=0;
    int last=1,fa[N],ch[N][26],l[N],vis[N],head[N];
    int r[N],sa[N],rk[N],h[N];
    char s[N];
    struct state{int x,y,v;}q[N];
    struct Edge{int u,v,next;}G[N<<1];
    inline void addedge(int u,int v){
        G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot;
    }
    void dfs(int u){
        if(r[u])sa[++sacnt]=r[u];
        for(int i=head[u];i;i=G[i].next)dfs(G[i].v);
    }
    void ins(int c,int pos){
        int p=last,np=++cnt;last=np;l[np]=l[p]+1;r[np]=pos;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
        if(!p)fa[np]=1;
        else{
            int q=ch[p][c];
            if(l[p]+1==l[q])fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];fa[np]=fa[q]=nq;
                for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
            }
        }
    }
    int main(){
        int f=0;
        scanf("%s",s+1);n=strlen(s+1);
        vis[1]=last=cnt=1;
        for(int i=n;i;i--)ins(s[i]-'a',i);
        for(int i=1;i<=cnt;i++)if(r[i]&&!vis[i])
        for(int pos=n,j=i;!vis[j];vis[j]=1,j=fa[j],--pos){
            pos=pos-l[j]+l[fa[j]]+1;q[++top]=(state){fa[j],j,s[pos]-'a'};
        }
        for(int i=1;i<=top;i++)c[q[i].v]++;
        for(int i=1;i<26;i++)c[i]+=c[i-1];
        for(int i=top;i;i--)rk[c[q[i].v]--]=i;
        for(;top;top--)addedge(q[rk[top]].x,q[rk[top]].y);
        dfs(1);
        for(int i=1;i<=n;i++)printf("%d ",sa[i]);puts("");
        for(int i=1;i<=n;i++)rk[sa[i]]=i;
        for(int i=1;i<=n;i++){
            int f=max(h[rk[i-1]]-1,0);    
            for(int j=sa[rk[i]-1];s[i+f]==s[j+f];f++);
            h[rk[i]]=f;
        }
        for(int i=2;i<=n;i++)printf("%d ",h[i]);
    }

    就这样,用sam就把这题水过去了~

  • 相关阅读:
    iOS开发UIKit框架-可视化编程-XIB
    ios swift例子源码网址总结
    两个单链表相交问题
    库函数atoi
    C++类型萃取
    【Swift】iOS导航栏错乱的原因
    【Swift】iOS裁剪或者压缩后出现的白边问题
    Linux进程调度分析
    【scala】可变与不可变的理解
    【scala】模式匹配
  • 原文地址:https://www.cnblogs.com/zcysky/p/7065732.html
Copyright © 2020-2023  润新知