• 后缀数组的倍增算法


    一、基数排序。

    题目描述:给你n个字符串,把它们排序。  n<=100000  (不要用sort水过,除非你在NOI的考场上)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #include<ctime>
     7 #include<algorithm>
     8 #define MAXN 100010
     9 using namespace std;
    10 int n,rank[MAXN],p[MAXN],sa[MAXN],cnt[MAXN];
    11 char s[MAXN][15];
    12 inline int read()
    13 {
    14     int x=0,f=1;  char ch=getchar();
    15     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
    16     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
    17     return x*f;
    18 }
    19 void Init()
    20 {
    21     n=read();
    22     for(int i=1;i<=n;i++)
    23     {
    24         char ch[15];
    25         scanf("%s",ch);
    26         for(int j=1;j<=10;j++)
    27             s[i][j]=j>strlen(ch)?'a'-1:ch[j-1];
    28     }
    29 }
    30 void Radix_sort()
    31 {
    32     for(int i=1;i<=n;i++)  sa[i]=i;
    33     for(int l=10;l>0;l--)
    34     {
    35         for(int i=1;i<=n;i++)  rank[i]=s[i][l]-'a'+1,p[i]=sa[i];
    36         for(int i=0;i<=26;i++)  cnt[i]=0;
    37         for(int i=1;i<=n;i++)  cnt[rank[i]]++;
    38         for(int i=1;i<=26;i++)  cnt[i]+=cnt[i-1];
    39         for(int i=n;i>=1;i--)  sa[cnt[rank[p[i]]]--]=p[i];
    40     }
    41 }
    42 void print()
    43 {
    44     for(int i=1;i<=n;i++)
    45         printf("%d ",sa[i]);
    46 }
    47 int main()
    48 {
    49     Init();
    50     Radix_sort();
    51     print();
    52     return 0;
    53 }
    View Code

    二、求后缀数组。

     1 int N,ans,rank[MAXN],sa[MAXN],p[MAXN],cnt[MAXN],tmp[MAXN],height[MAXN];
     2 char s[MAXN];
     3 bool equ(int x,int y,int l) {return rank[x]==rank[y]&&rank[x+l]==rank[y+l];}
     4 void doubling()
     5 {
     6     for(int i=1;i<=N;i++)  rank[i]=s[i],sa[i]=i;
     7     for(int pos=0,sig=255,l=0,i;pos<N;sig=pos)
     8     {
     9         for(i=N-l+1,pos=0;i<=N;i++)  p[++pos]=i;
    10         for(i=1;i<=N;i++)  if(sa[i]>l)  p[++pos]=sa[i]-l;
    11         for(i=1;i<=sig;i++)  cnt[i]=0;
    12         for(i=1;i<=N;i++)  cnt[rank[i]]++;
    13         for(i=1;i<=sig;i++)  cnt[i]+=cnt[i-1];
    14         for(i=N;i;i--)  sa[cnt[rank[p[i]]]--]=p[i];
    15         for(pos=0,i=1;i<=N;i++)  
    16             tmp[sa[i]]=equ(sa[i],sa[i-1],l)?pos:++pos;
    17         for(int i=1;i<=N;i++)  rank[i]=tmp[i];
    18         l=!l?1:l<<1;
    19     }
    20 }
    View Code

    三、height数组

     1 void get_height()
     2 {
     3     for(int i=1,j=0,k;i<=N;i++)
     4     {
     5         if(!(k=sa[rank[i]-1]))  {j=0;  continue;}
     6         if(j)  j--;
     7         while(s[i+j]==s[k+j])  j++;
     8         height[rank[i]]=j;
     9         ans=max(ans,j);
    10     }
    11 }
    View Code
  • 相关阅读:
    [ELK] Elasticsearch 安装/配置、启动/停止、加节点/重启
    [ELK] Elastic Stack 的安全性预览
    [Gin] gin.H{} 与 map[string]interface{}
    [Go] 浅谈 Golang struct 与 PHP class 的相似
    [FAQ] Git 修改最后一次的提交人和提交时间 ?
    [Blockchain] 开发完真实的 DApp 后才能得出的结论与看法
    Android 5.0 Phone初始化分析
    推荐一个Android开发懒人库 -- ButterKnife
    ffmpeg 移植到 android 并使用
    为app录制展示gif
  • 原文地址:https://www.cnblogs.com/chty/p/5842018.html
Copyright © 2020-2023  润新知