• 【模板】后缀数组模板


    这几天在学后缀数组(补题补到绝望决定来学点新东西),等我再学的明白一点,并且有时间心情好的时候(遥遥无期,而且估计写了也没人看),就来写一篇后缀数组的知识点博客~

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 const int maxn=10000;
     8 char s[maxn];
     9 int sa[maxn],t[maxn],t1[maxn],c[maxn];
    10 int n;
    11 void build_sa(int m){
    12     int *x=t,*y=t1;
    13     for(int i=0;i<m;i++)c[i]=0;
    14     for(int i=0;i<n;i++)c[x[i]=s[i]]++;
    15     for(int i=1;i<m;i++)c[i]+=c[i-1];
    16     for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    17 
    18     for(int k=1;k<=n;k<<=1){
    19         int p=0;
    20         for(int i=n-k;i<n;i++)y[p++]=i;
    21         for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
    22         for(int i=0;i<m;i++)c[i]=0;
    23         for(int i=0;i<n;i++)c[x[y[i]]]++;//这里为啥是这样?一会结合基数排序想一下
    24         for(int i=1;i<m;i++)c[i]+=c[i-1];
    25         for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
    26         swap(x,y);
    27         p=1,x[sa[0]]=0;
    28         for(int i=1;i<n;i++)
    29           x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
    30         if(p>=n)break;
    31         m=p;
    32     }
    33 }
    34 
    35 int m;
    36 int cmp_suffix(char* pattern,int p){
    37     return strncmp(pattern,s+sa[p],m);
    38 }
    39 int find(char *P){
    40     m=strlen(P);
    41     if(cmp_suffix(P,0)<0)return -1;
    42     if(cmp_suffix(P,n-1)>0)return -1;
    43     int L=0,R=n-1;
    44     while(R>=L){
    45         int M=L+(R-L)/2;
    46         int res=cmp_suffix(P,M);
    47         if(!res)return M;
    48         if(res<0)R=M-1;
    49         else L=M+1;
    50     }
    51 }
    52 int rank[maxn],height[maxn];//rank数组是后缀i的排名,height数组是sa[i-1]和sa[i]的最长公共前缀
    53 //后缀j和k的LCP长度等于RMQ(height,rank[j]+1,rank[k])。
    54 void getHeight(){
    55     int k=0;
    56     for(int i=0;i<n;i++)rank[sa[i]]=i;
    57     for(int i=0;i<n;i++){
    58         if(k)k--;
    59         int j=sa[rank[i]-1];
    60         while(s[i+k]==s[j+k])k++;
    61         height[rank[i]]=k;
    62     }
    63 }
    64 
    65 int d[maxn][30];
    66 void RMQ_init(){
    67     for(int i=0;i<n;i++){
    68         d[i][0]=height[i];
    69     }
    70     for(int i=1;(1<<i)<=n;i++){
    71         for(int j=0;(1<<i)+j<n;j++){
    72             d[j][i]=min(d[j][i-1],d[j+(1<<(i-1))][i-1]);
    73         }
    74     }
    75 }
    76 
    77 int LCP(int k,int j){
    78     if(rank[k]>rank[j])
    79         swap(k,j);
    80     int L=rank[k]+1,R=rank[j];
    81     int i=0;
    82     while((1<<(i+1))<=R-L+1)i++;
    83     return min(d[L][i],d[R-(1<<i)+1][i]);
    84 }
    85 
    86 int main(){
    87     scanf("%s",s);
    88     n=strlen(s);
    89     build_sa('a'+27);
    90     getHeight();
    91     RMQ_init();
    92     int j,k;
    93     while(scanf("%d%d",&j,&k)!=EOF&&(j||k)){
    94         printf("%d
    ",LCP(j,k));
    95     }
    96 return 0;
    97 }
  • 相关阅读:
    [iOS Animation]-CALayer 图像IO
    weblogic集群
    mysql相关函数及用法
    mysql导出导入数据库
    java多线程实现复制功能并统计进度
    java多线程模拟实现12306售票
    Oracle中的常用数据类型
    jdbc连接mysql和oracle数据库-java
    将字符串插入到光标指定位置-js
    二维数组模拟实现酒店管理系统-java
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9440281.html
Copyright © 2020-2023  润新知