后缀数组SA

变量

  • int k1[i]\texttt{int k1[i]}:第一关键字。
  • int k2[i]\texttt{int k2[i]}:第二关键字。
  • int c[i]\texttt{int c[i]}:第 ii 个关键字出现的次数。
  • int sa[i]\texttt{int sa[i]}:排名为 ii 的后缀的编号。

函数

  • void qsa(int n,int m,string s)\texttt{void qsa(int n,int m,string s)}:求长度为 nn,字符串种类为 1m1\sim m 的字符串 ssSA\text{SA} 数组(下标从 11 开始)。

代码

struct SA{
	int k1[N],k2[N],c[N],sa[N],rk[N],h[N];
	void qsa(int n,int m,string s){
		for(int i=1;i<=n;i++)c[k1[i]=s[i]]++;
		for(int i=1;i<=m;i++)c[i]+=c[i-1];
		for(int i=1;i<=n;i++)sa[c[k1[i]]--]=i;
		for(int b=1,tot;b<=n;b<<=1){
			tot=0;
			for(int i=n-b+1;i<=n;i++)k2[++tot]=i;
			for(int i=1;i<=n;i++)
				if(sa[i]>b)k2[++tot]=sa[i]-b;
			for(int i=1;i<=m;i++)c[i]=0;
			for(int i=1;i<=n;i++)c[k1[i]]++;
			for(int i=1;i<=m;i++)c[i]+=c[i-1];
			for(int i=n;i>=1;i--)
				sa[c[k1[k2[i]]]--]=k2[i],k2[i]=0;
			swap(k1,k2);tot=1;k1[sa[1]]=1;
			for(int i=2;i<=n;i++)
				if(k2[sa[i]]==k2[sa[i-1]]&&k2[sa[i]+b]==k2[sa[i-1]+b])
					k1[sa[i]]=tot;
				else k1[sa[i]]=++tot;
			if(tot==n)return;
			m=tot;
		}
		for(int i=1;i<=n;i++)rk[sa[i]]=i;
		for(int i=1,k=0;i<=n;i++){
			if(k)k--;
			while(s[i+k]==s[sa[rk[i]-1]+k])k++;
			h[rk[i]]=k;
		}
	}
}st;
posted @ 2023-10-18 13:07  luckydrawbox  阅读(9)  评论(0)    收藏  举报  来源