zoukankan      html  css  js  c++  java
  • 数据结构:后缀数组模板

    点击查看折叠代码块
    /*
    Str :需要处理的字符串(长度为Len) 
    Suffix[i] :Str下标为i ~ Len的连续子串(即后缀) 
    Rank[i] : Suffix[i]在所有后缀中的排名 
    SA[i] : 满足Suffix[SA[1]] < Suffix[SA[2]] …… < Suffix[SA[Len]],即排名为i的后缀为Suffix[SA[i]] (与Rank是互逆运算) 
    
    最长公共前缀(Longest Common Prefix,LCP)
    Heigth[i] : 表示Suffix[SA[i]]和Suffix[SA[i - 1]]的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀
    H[i] : 等于Height[Rank[i]],也就是后缀Suffix[i]和它前一名的后缀的最长公共前缀 
    而两个排名不相邻的最长公共前缀定义为排名在它们之间的Height的最小值。 
    */
    const int N = 1e5+10;
    const int D = 18;
    int t1[N],t2[N],c[N],lg2[N];
    struct suffix_array{
        int str[N],sa[N],rank[N],height[N];
        int rmq[D][N];
        bool cmp(int *r,int a,int b,int l){
            return r[a]==r[b]&&r[a+l]==r[b+l];
        }
        void da(int n,int m){
            n++; int i, j, p, *x = t1, *y = t2;
            for(i=0;i<m;++i) c[i]=0;
            for(i=0;i<n;++i) c[x[i]=str[i]]++;
            for(i=1;i<m;++i) c[i]+=c[i-1];
            for(i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
            for(j=1;j<n;j<<=1){
                p=0;
                for(i=n-j;i<n;++i) y[p++]=i;
                for(i=0;i<n;++i) if(sa[i]>=j) y[p++]=sa[i]-j;
    
                for(i=0;i<m;++i) c[i]=0;
                for(i=0;i<n;++i) c[x[y[i]]]++;
                for(i=1;i<m;++i) c[i]+=c[i-1];
                for(i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
    
                swap(x,y); p=1; x[sa[0]]=0;
                for(i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
                if(p>=n) break; m=p;
            }
            int k=0; n--;
            for(i=0;i<=n;++i) rank[sa[i]]=i;
            for(i=0;i<n;++i){
                if(k) k--;
                j=sa[rank[i]-1];
                while(str[i+k]==str[j+k]) ++k;
                height[rank[i]]=k;
            }
        }
        void initlcp(int n){
            for(int i=1;i<=n;++i)
                rmq[0][i]=height[i];
            for(int k=1;k<=lg2[n];++k)//做倍增
                for(int i=1;i+(1<<k)-1<=n;++i)
                    rmq[k][i]=min(rmq[k-1][i],rmq[k-1][i+(1<<(k-1))]);
        }
        int lcp(int a,int b){
            a=rank[a]; b=rank[b];
            if(a>b) swap(a,b); a+=1;
            int d=lg2[b-a+1];
            return min(rmq[d][a],rmq[d][b-(1<<d)+1]);
        }
    }sa;
    char s[N]; int n;
    int p[N][3],f[3];
    bool cmp(int a,int b){
        for(int i=0,l,l1,l2;i<3;++i){
            if(p[a][i]==n) return true;  
            if(p[b][i]==n) return false;
            l1=p[a][i+1]-p[a][i]-1; l2=p[b][i+1]-p[b][i]-1;
            if(l1==0&&l2==0) continue;
            else if(l1==0) return true;
            else if(l2==0) return false;
            l=sa.lcp(p[a][i]+1,p[b][i]+1);
            if(l==min(l1,l2)){
                if(l1==l2) continue;
                else return l1<l2;
            }else return sa.str[p[a][i]+1+l]<sa.str[p[b][i]+1+l];
        }
        return false;
    }
    lg2[0]=-1;
    for(int i=1;i<N;++i) lg2[i]=(i&(i-1))?lg2[i-1]:lg2[i-1]+1;//预处理log
        
    
    你将不再是道具,而是成为人如其名的人
  • 相关阅读:
    转:C#操作摄像头
    C# Memcached缓存
    WCF:调用方未由服务器进行身份验证
    SQL Server 存储过程进行分页查询
    SQL Server T-SQL高级查询
    C#设计模式总结(转)
    C#中构造函数和析构函数区别
    C#: static关键字的作用(转)
    C#结构体和类的区别(转)
    .NET多线程编程(转)
  • 原文地址:https://www.cnblogs.com/wsl-lld/p/13393463.html
Copyright © 2011-2022 走看看