后缀数组(๑Ő௰Ő๑)ノ“

本文详细介绍了后缀数组的构造方法——倍增求SA,以及LCP(最长公共前缀)的计算,并提供了多种利用后缀数组和LCP解决字符串问题的实例,包括本质不同子串个数、区间LCP求和等。通过这些习题,帮助读者深入理解并掌握后缀数组和LCP在字符串算法中的应用。
摘要由CSDN通过智能技术生成

后缀数组与LCP

后缀数组

首先,将一个字符串的所有后缀按字典序排序。
后缀数组 s a [ i ] sa[i] sa[i]:表示所有后缀在排完序后,排名为 i i i 的后缀在原串中的位置。
名次数组 r a n k [ i ] rank[i] rank[i]:表示所有后缀在排序完后,原字符串中第 i i i 名现在的排名。
显然, s a sa sa r a n k rank rank 是互逆的,即 r a n k [ s a [ i ] ] = i , s a [ r a n k [ i ] ] = i ; rank[sa[i]]=i,sa[rank[i]]=i; rank[sa[i]]=i,sa[rank[i]]=i;

倍增求sa

我们求后缀的排名,可以每次求出区间 [ i , i [i,i [i,i+ 2 ∗ w 2∗w 2w 1 ] 1] 1] 的排名, w w w= 1 , 2 , 4 , 8... 1,2,4,8... 1,2,4,8... [ i , i [i,i [i,i+ 2 ∗ w 2∗w 2w 1 ] 1] 1] 的排名,我们可以将它分为 [ i , i [i,i [i,i+ w w w- 1 ] 1] 1] [ i [i [i+ w , i w,i w,i+ 2 ∗ w 2∗w 2w 1 ] 1] 1] 两部分。
所有可以以 [ i , i [i,i [i,i+ w w w- 1 ] 1] 1] 的排名为第一关键字, [ i [i [i+ w , i w,i w,i+ 2 ∗ w 2∗w 2w 1 ] 1] 1]的排名为第二关键字,来对所有的 i i i 排序。
于是我们就可以用个 s o r t sort sort O ( n l o g 2 n ) O(nlog^2 n) O(nlog2n) 内进行后缀排序了。

CODE

int rnk[N],sa[N],h[N];
struct p{
   
	int a,b,id;
}p[N];
bool cmp(const P&a,const P&b){
   
	return a.a==b.a?a.b<b.b:a.a<b.a;
}
int init_sa(char *s){
   
	int n=std::strlen(s);
	for(int i=0;i<n;i++) rnk[i]=s[i];
	for(int i=1;i<n;i<<=1){
   
		for(int j=0;j<n;j++)
			p[j]=P{
   rnk[j],j+1>=n?-1:rnk[j+1],j};
		std::sort(p,p+n,cmp);
		int c;
		for(int j=0;j<n;j++){
   
			rnk[p[j].id]=c;
			c+=!(p[j].a==p[j+1].a&&p[j].b==p[j+1].b);
		}
	}
}

LCP(最长公共前缀)

LCP,即最长公共前缀,Longgest Common Prefix。
l c p ( i , j ) lcp(i,j) lcp(i,j) 表示 s a i sa_i sai s a j sa_j saj 的最长公共前缀。
则对任意

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值