當前位置:
首頁 >
后缀数组学习笔记
發布時間:2023/11/27
25
豆豆
后綴數組倍增預處理
#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#define N 2200000
#define L 2000000
#define eps 1e-7
#define inf 1e9+7
#define ll long long
using namespace std;
inline int read()
{char ch=0;int x=0,flag=1;while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*flag;
}
char s[N];
int n,m;
int c[N],x[N],y[N],sa[N];
int main()
{scanf("%s",s+1);n=strlen(s+1);m=122;for(int i=1;i<=n;i++)++c[x[i]=s[i]];for(int i=1;i<=m;i++)c[i]+=c[i-1];for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;for(int k=1;k<=n;k<<=1){//sa[i]當前是按照第一關鍵字排序的第i名的后綴編號//y[i]是第二關鍵字的排名為i的數,它第一關鍵字的位置,根據定義,下面是sa[i]-k int num=0;for(int i=n-k+1;i<=n;i++)y[++num]=i;for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k; for(int i=1;i<=m;i++)c[i]=0;for(int i=1;i<=n;i++)c[x[i]]++;//按照第一關鍵字扔到桶里。for(int i=1;i<=m;i++)c[i]+=c[i-1];//求一下前綴。for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;//按照第二關鍵字的順序倒著取//先看一下這個第二關鍵字對應的第一關鍵字的位置//用x來確定一下排名它當前的排名//用桶來算出它在下一次會排在第幾名//根據sa數組的定義,在下一輪中,sa[這個排名]=第一關鍵字的位置 swap(x,y);//只是為了避免多開一個數組,利用y來做一個x的拷貝而已 x[sa[1]]=num=1;for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?num:++num; //這里的y數組是之間的x數組 //分別比較這一個和上一個的兩個關鍵字是否同時相同。 if(num==n)break;m=num; }for(int i=1;i<=n;i++)printf("%d ",sa[i]);return 0;
}
處理height數組
height[i]=lcp(sa[i],sa[i-1])
為了得到height數組,可以先處理出一個h數組
h[i]=height[rank[i]]
由此可以推出height[i]=h[sa[i]]
考慮暴力計算這個h[i]數組是O(n^2)的
但這里有一個很重要的性質,即h[i]>=h[i-1]-1
手動模擬一下即可證明。
因此,這個東西可以O(n)來求。
void calheight()
{for(int i=1,k=0;i<=n;i++){if(k)k--;int j=sa[rank[i]-1];while(s[i+k]==s[j+k])k++;height[rank[i]]=k;}
} 其中這個k就代表了h[i]的意思
轉載于:https://www.cnblogs.com/Creed-qwq/p/10096145.html
總結
- 上一篇: “鹤有不群者”下一句是什么
- 下一篇: python 字符串内容