后缀数组总结

Posted fexuile

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后缀数组总结相关的知识,希望对你有一定的参考价值。

感觉SA还是有点用处的所以还是用用的好。

定义

首先是一些定义,这是后缀数组的基础。

\(sa_i\)表示按照字典序从小到大排序后第\(i\)个串是\(sa_i\)这个后缀。
\(rank_i\)表示\(i\)这个后缀对应的是第几个(排名)。
\(height_i\)表示的是\(lcp(sa_i,sa_i-1)\)的长度。

代码其实很容易,就是一个基数排序+倍增,也很容易理解(

主要是应用方面还是要多做一些题目的好。

代码实现

/*
  mail: mleautomaton@foxmail.com
  author: MLEAutoMaton
  This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi()
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0')if(ch=='-')f=-1;ch=getchar();
    while(ch>='0' && ch<='9')sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();
    return f*sum;

const int N=4000010,Mx=510;
int t[N],n,k,x[N],sa[N],height[N],rnk[N],y[N];
char a[N];
bool cmp(int a,int b,int lim)
    return (y[a]==y[b] && y[a+lim]==y[b+lim]);

void get_sa()
    int m=150;
    for(int i=1;i<=m;i++)t[i]=0;
    for(int i=1;i<=n;i++)t[x[i]=a[i]]++;
    for(int i=1;i<=m;i++)t[i]+=t[i-1];
    for(int i=n;i;i--)sa[t[x[i]]--]=i;
    int p=0;
    for(int lim=1;p<=n && lim<=n;lim<<=1)
        p=0;
        for(int i=n-lim+1;i<=n;i++)y[++p]=i;
        for(int i=1;i<=n;i++)if(sa[i]>lim)y[++p]=sa[i]-lim;
        for(int i=1;i<=m;i++)t[i]=0;
        for(int i=1;i<=n;i++)t[x[y[i]]]++;
        for(int i=1;i<=m;i++)t[i]+=t[i-1];
        for(int i=n;i;i--)sa[t[x[y[i]]]--]=y[i];
        swap(x,y);x[sa[1]]=1;p=2;
        for(int i=2;i<=n;i++)x[sa[i]]=cmp(sa[i],sa[i-1],lim)?p-1:p++;
        m=p;
    
    for(int i=1;i<=n;i++)rnk[sa[i]]=i;
    for(int i=1,j=0;i<=n;i++)
        j=max(0,j-1);int lst=sa[rnk[i]-1];
        while(a[i+j]==a[lst+j])j++;
        height[rnk[i]]=j;
    
//  for(int i=1;i<=n;i++)printf("%d %d\n",sa[i],height[i]);

bool check(int mid)
    int sum=1;
    for(int i=1;i<=n;i++)
        if(height[i]>=mid)
            sum++;
            if(sum>=k)return true;
        
        else sum=1;
    return false;

int main()
//  n=gi();k=gi();
//  for(int i=1;i<=n;i++)a[i]=gi();
    scanf("%s",a+1);n=strlen(a+1);
    get_sa();
/*  int l=0,r=n,ans=0;
    while(l<=r)
        int mid=(l+r)>>1;
        if(check(mid))l=mid+1;ans=mid;
        else r=mid-1;
        */
//  printf("%d\n",ans);
    for(int i=1;i<=n;i++)printf("%d%c",sa[i],i==n?'\n':' ');
    return 0;

以上是关于后缀数组总结的主要内容,如果未能解决你的问题,请参考以下文章

后缀数组总结

后缀数组总结

后缀数组模板题总结

后缀数组总结

学习总结-后缀数组

知识总结后缀数组(Suffix_Array)