zoukankan      html  css  js  c++  java
  • 模板 后缀数组

    (要点写注释里了)代码:求SA

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 int has[2000000];//桶,用于基数排序,ASCII字符集0~127
     5 int sa[2000000];//后缀数组,意为排名为i的后缀起始位置 
     6 int tmr[2000000];//temp_rank为构建rank的临时数组后期需要去重
     7 int rank[2000000];//排名,与sa互为逆映射,为以i起始的后缀的排名 
     8 char str[2000000];
     9 int len,cnt;
    10 bool Ssame(int a,int b,int l)//去重函数,意为判断以a,b开始长度为l的子串是否相同 
    11 {
    12     if(a+l>len||b+l>len)
    13         return false;//若有一个末尾超过总长,一定可以判定两串不相同
    14     return (rank[a]==rank[b])&&(rank[a+l]==rank[b+l]);//两串排名均相同则相同 
    15 }
    16 int main()
    17 {
    18     scanf("%s",str+1);
    19     len=strlen(str+1);
    20     for(int i=1;i<=len;i++)
    21         has[str[i]]++;//构建桶 
    22     for(int i=0;i<128;i++)
    23         if(has[i])
    24             tmr[i]=++cnt;//tmr在第一次构建的时候意为字符所在排名 
    25     for(int i=1;i<128;i++)
    26         has[i]+=has[i-1];//基数排序参数 
    27     for(int i=1;i<=len;i++)
    28     {
    29         rank[i]=str[i]; 
    30         sa[has[str[i]]--]=i;
    31     }
    32     /*第一次从文本串转化为rank数组,其实是无需离散化的*/
    33     for(int k=1;cnt!=len;k*=2)
    34     {
    35         cnt=0;
    36         for(int i=0;i<=len;i++)
    37             has[i]=0;//清空 
    38         for(int i=1;i<=len;i++)
    39             has[rank[i]]++;//本质是rank的排序 
    40         for(int i=1;i<=len;i++)
    41             has[i]+=has[i-1];//构建桶 
    42         for(int i=len;i;i--)//顺序 
    43             if(sa[i]>k)
    44                 tmr[sa[i]-k]=has[rank[sa[i]-k]]--;//有前半部分 
    45         for(int i=1;i<=k;i++)
    46             tmr[len-i+1]=has[rank[len-i+1]]--;
    47         for(int i=1;i<=len;i++)
    48             sa[tmr[i]]=i;
    49         for(int i=1;i<=len;i++)
    50             if(Ssame(sa[i],sa[i-1],k))
    51                 tmr[sa[i]]=cnt;
    52             else
    53                 tmr[sa[i]]=++cnt;
    54         for(int i=1;i<=len;i++)
    55             rank[i]=tmr[i];
    56     }
    57     for(int i=1;i<=len;i++)
    58         printf("%d ",sa[i]);
    59     puts("");
    60     return 0;
    61 }

     查询height:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using std::max;
     5 const int N=200000;
     6 int tmr[N];
     7 int rnk[N];
     8 int sa[N];
     9 int has[N];
    10 int hgt[N];
    11 char str[N];
    12 int len;
    13 int cnt;
    14 bool Same(int a,int b,int l)
    15 {
    16     if(a+l>len||b+l>len)
    17         return false;
    18     return (rnk[a]==rnk[b])&&(rnk[a+l]==rnk[b+l]);
    19 }
    20 int main()
    21 {
    22     scanf("%s",str+1);
    23     len=strlen(str+1);
    24     for(int i=1;i<=len;i++)
    25         has[str[i]]++;
    26     for(int i=0;i<128;i++)
    27         if(has[i])
    28             tmr[i]=++cnt;
    29     for(int i=1;i<128;i++)
    30         has[i]+=has[i-1];
    31     for(int i=1;i<=len;i++)
    32     {
    33         rnk[i]=tmr[str[i]];
    34         sa[has[str[i]]--]=i;
    35     }
    36     for(int k=1;cnt!=len;k<<=1)
    37     {
    38         cnt=0;
    39         for(int i=0;i<=len;i++)
    40             has[i]=0;
    41         for(int i=1;i<=len;i++)
    42             has[rnk[i]]++;
    43         for(int i=1;i<=len;i++)
    44             has[i]+=has[i-1];
    45         for(int i=len;i;i--)
    46             if(sa[i]>k)
    47                 tmr[sa[i]-k]=has[rnk[sa[i]-k]]--;
    48         for(int i=1;i<=k;i++)
    49             tmr[len-i+1]=has[rnk[len-i+1]]--;
    50         for(int i=1;i<=len;i++)
    51             sa[tmr[i]]=i;
    52         for(int i=1;i<=len;i++)
    53             if(Same(sa[i],sa[i-1],k))
    54                 tmr[sa[i]]=cnt;
    55             else
    56                 tmr[sa[i]]=++cnt;
    57         for(int i=1;i<=len;i++)
    58             rnk[i]=tmr[i];
    59     }
    60     for(int i=1;i<=len;i++)
    61     {
    62         if(rnk[i]==1)
    63             continue;
    64         int j=max(1,hgt[rnk[i-1]]-1);
    65         while(str[i+j-1]==str[sa[rnk[i]-1]+j-1])
    66             hgt[rnk[i]]=j++;
    67     }
    68     for(int i=1;i<=len;i++)
    69         printf("%d ",sa[i]);
    70     puts("");
    71     for(int i=2;i<=len;i++)
    72         printf("%d ",hgt[i]);
    73     puts("");
    74     return 0;
    75 }
  • 相关阅读:
    迷の“良心”膜你赛总结*3
    bzoj1704/poj3276[Usaco2007 Mar]Face The Right Way自动转身机
    poj 1840 -- Eqs
    poj 3274 -- Gold Balanced Lineup
    poj 3349 -- Snowflake Snow Snowflakes
    poj 2442 -- Sequence
    BestCoder Round #1 1002 项目管理 (HDU 4858)
    BestCoder Round #1 1001 逃生 (HDU 4857)
    poj 1273 -- Drainage Ditches
    poj 1149 -- PIGS
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9693692.html
Copyright © 2011-2022 走看看