• SA后缀数组


    需要再多去理解

      1 #include<cstdio> 
      2 #include<cstring>
      3 #include<cmath>
      4 #include<ctime>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<set>
      9 #define inf (0x7fffffff)
     10 #define l(a) ((a)<<1)
     11 #define r(a) ((a)<<1|1)
     12 #define b(a) (1<<(a))
     13 #define rep(i,a,b) ;for(int i=a;i<=(b);i++)
     14 #define clr(a) memset(a,0,sizeof(a))
     15 typedef long long ll;
     16 typedef unsigned long long ull;
     17 using namespace std;
     18 int readint(){
     19     int t=0,f=1;char c=getchar();
     20     while(!isdigit(c)){
     21         if(c=='-') f=-1;
     22         c=getchar();
     23     }
     24     while(isdigit(c)){
     25         t=(t<<3)+(t<<1)+c-'0';
     26         c=getchar();
     27     }
     28     return t*f;
     29 }
     30 const int maxn=2000009;
     31 int n,m=256,mn=maxn,sa1[maxn],a[maxn],sum[maxn],sa[maxn],rank[maxn],height[maxn];//sa与rank意义相反 
     32 char s[maxn];
     33 void cal_SA(){
     34     clr(sum);
     35     rep(i,1,n) sum[rank[i]=s[i]]++;//求初始rank
     36     rep(i,1,m) sum[i]+=sum[i-1];
     37     for(int i=n;i;i--) sa[sum[rank[i]]--]=i;///基数排序求初始sa 注意这个奇妙的操作! 
     38     for(int l=1;l<n;l<<=1){
     39         //printf("rank==");rep(i,1,n) printf("%d ",rank[i]);puts("");
     40         //printf("sa==");rep(i,1,n) printf("%d ",sa[i]);puts("");
     41         
     42         int cnt=0;
     43         rep(i,n-l+1,n) sa1[++cnt]=i;//后面的第二关键字为最小 
     44         rep(i,1,n) if(sa[i]>l) sa1[++cnt]=sa[i]-l;//利用sa对第二关键字的排序(sa1即第二关键字的sa) 
     45         
     46         //printf("sa1==");rep(i,1,n) printf("%d ",sa1[i]);puts("");
     47         
     48         rep(i,1,n) a[i]=rank[sa1[i]];//a为按第二关键字排序后的rank 注意! 
     49         
     50         //printf("a==");rep(i,1,n) printf("%d ",a[i]);puts("");
     51          
     52         clr(sum);rep(i,1,n) sum[a[i]]++;
     53         rep(i,1,n) sum[i]+=sum[i-1];
     54         for(int i=n;i;i--) sa[sum[a[i]]--]=sa1[i];//求出新的sa 
     55         //综合第一关键字对a排序 和上面类似的奇妙操作(a按第二关键字排序了,所以这样倒着统计即可) 
     56         
     57         //printf("sa==");rep(i,1,n) printf("%d ",sa[i]);puts("");
     58     
     59         cnt=0;
     60         rep(i,1,n) a[i]=rank[i];//将rank的值保存出来 
     61         rep(i,1,n){
     62             rank[sa[i]]=(a[sa[i-1]]==a[sa[i]]&&a[sa[i-1]+l]==a[sa[i]+l])?cnt:++cnt;
     63         }//计算出新的rank 此处要利用rank考虑字符串相同的情况 
     64         
     65         //printf("rank==");rep(i,1,n) printf("%d ",rank[i]);puts("");
     66         //puts("");
     67         
     68         if(cnt==n) break;//cnt==n即排序完成
     69     }
     70     /*rep(i,1,n){
     71         printf("%d",rank[i]);
     72         putchar(i==n?'
    ':' ');
     73     }*/
     74     rep(i,1,n){
     75         printf("%d",sa[i]);
     76         putchar(i==n?'
    ':' ');
     77     }
     78 }
     79 void cal_Height(){//height[i]=suffix(sa[i-1])和suffix(sa[i])的最大公共前缀 
     80     //suffix(i)和suffix(j)的最大公共前缀为min(height[rank[i]+1],height[rank[i]+2]...height[rank[j]]) 
     81     int k=0;
     82     rep(i,1,n){
     83         if(k) k--;
     84         int j=sa[rank[i]-1];
     85         while(s[i+k]==s[j+k]) k++;
     86         height[rank[i]]=k;
     87     }//利用h数组(h[i]=height[rank[i]])的性质(h[i]>=h[i-1]-1)(可证)计算height 
     88     rep(i,2,n){
     89         printf("%d",height[i]);
     90         putchar(i==n?'
    ':' ');
     91     }
     92 }
     93 void init(){
     94     scanf("%s",s+1);n=strlen(s+1);
     95     rep(i,1,n) sum[int(s[i])]=1;
     96     rep(i,1,m) sum[i]+=sum[i-1];
     97     rep(i,1,n) s[i]=sum[s[i]-1]+1;//将字符串转变为从1开始的整数 
     98 }
     99 int main(){
    100     //freopen("#input.txt","r",stdin);
    101     //freopen("#output.txt","w",stdout);
    102     init();
    103     cal_SA();
    104     cal_Height();
    105     //fclose(stdin);
    106     //fclose(stdout);
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    Extjs4 关于设置form中所有子控件为readOnly属性的解决方案
    Chrome调试(转)
    ExtJS4 动态加载
    CSS display和visibility的用法和区别
    利用Java调用OpenCV进行人脸识别
    Mac上安装openCV(Java版本)
    关于mysql的Fetch Time 和 Duration Time
    数据库相关中间件介绍
    JVM和java应用服务器调优
    探索 ConcurrentHashMap 高并发性的实现机制
  • 原文地址:https://www.cnblogs.com/chensiang/p/7868485.html
Copyright © 2020-2023  润新知