• 后缀数组(倍增) 时间nlogn 空间n


    模板   

     1 struct SuffixArray{
     2     int sa[maxn];//排名为i的后缀的起始下标
     3     int Rank[maxn];//起始下标为i的后缀排名
     4     int height[maxn];//排名为i和i-1的最长公共前缀
     5     int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
     6 
     7     int cmp(int *r, int a,int b,int l){//双关键字排序的比较
     8         return r[a]==r[b] && r[a+l]==r[b+l];
     9     }
    10 
    11     void da(int *r,int n,int m){
    12         ///r表示原数组,sa表示排名为i的下标,n表示r的大小+1,m表示字符的范围
    13         ///注意使用时如果r的大小为n,那么应传入n+1
    14         //x为第一关键字,y为第二关键字
    15         int i,k,p,*x = wa,*y = wb,*t;
    16         //长度为1时的基数排序
    17         for(i=0;i<m;i++) ws[i] = 0;
    18         for(i=0;i<n;i++) ws[x[i] = r[i]] ++;
    19         for(i=0;i<m;i++) ws[i] += ws[i-1];
    20         for(i=n-1;i>=0;i--) sa[-- ws[x[i]]] = i;
    21         //主要循环,k倍增
    22         for(k=1,p=1; p<n; k*=2, m=p){
    23             //以下两行代码实现了对第二关键字的排序
    24             for(p=0,i=n-k;i<n;i++) y[p++] = i;
    25             for(i=0;i<n;i++){
    26                 if(sa[i] >= k){
    27                     y[p++] = sa[i] - k;
    28                 }
    29             }
    30             //提取出每个子串的第一关键字
    31             for(i=0;i<n;i++){
    32                 wv[i] = x[y[i]];
    33             }
    34             //基数排序
    35             for(i=0;i<m;i++) ws[i]=0;
    36             for(i=0;i<n;i++) ws[wv[i]]++;
    37             for(i=1;i<m;i++) ws[i]+=ws[i-1];
    38             for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
    39             t=x,x=y,y=t;
    40             for(p=1,x[sa[0]]=0,i=1;i<n;i++)
    41                 x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++;
    42         }
    43     }
    44 
    45     //求rank数组与height数组
    46     void cal(int *r,int n){
    47         ///此处传入n即可
    48         int i,j,k=0;
    49         for(i=1;i<=n;i++) Rank[sa[i]] = i;
    50         for(i=0;i<n;i++){
    51             if(k > 0) k--;
    52             j=sa[Rank[i]-1];
    53             while(r[i+k] == r[j+k]) k++;
    54             height[Rank[i]] = k;
    55         }
    56 
    57         //for(i=0;i<n;height[Rank[i++]]=k)
    58         //for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
    59     }
    60 
    61     /*使用方法
    62     da(r,n+1,m);
    63     cal(r,n);*/
    64 }SA;
  • 相关阅读:
    python函数函数嵌套分析步骤与递归函数
    解决Navicat运行sql文件报错:1292
    SOAP与REST,有什么不同?
    bcrypt vs crypto vs cryptojs
    bcryptjs加密如何工作
    AOP(面向切面编程)
    javascript语言搞笑图
    js中函数声明先提升还是变量先提升
    CSS的单位及css3的calc()及line-height百分比
    Vue 项目性能优化 — 实践指南(网上最全 / 详细)
  • 原文地址:https://www.cnblogs.com/yZiii/p/7400660.html
Copyright © 2020-2023  润新知