首页 > 其他分享 >后缀数组(SA)

后缀数组(SA)

时间:2024-05-17 21:42:14浏览次数:25  
标签:后缀 height int 数组 SA sa rk

后缀数组(SA)

并非指数字的后缀,而针对字符串而生的算法。

字符串的后缀指是指从某个位置开始到整个串末尾结束的一个特殊子串。

后缀排序

将所有后缀按照字典序排序,利用计数排序时间+倍增复杂度为\(O(nlogn)\) 。

\(sa[i]:\)排名为\(i\)的后缀的起始位置。

\(rk[i]:\)起始位置为\(i\)的后缀的排名。

\(sa[rk[i]]=rk[sa[i]]=i\)。

\(tot[i]:\)计数排序。

倍增排序示意图:

\(rk\)数组的值在排序过程中可重,但最终不能重复。

\(sa\)数组的值在过程与最终都不能重复。

先求出\(sa\)数组再求\(rk\)数组。

height 数组

\(lcp:\)(最长公共前缀)

height 数组的定义

\(height[i]=lcp(sa[i],sa[i-1])\),即第 $i $名的后缀与它前一名的后缀的最长公共前缀。

\(height[1]\) 可以视作 \(0\)。

引理

\(height[rk[i]] \ge height[rk[i - 1]] - 1\)

struct SA{
	int rk[N], sa[N], sec[N], rk1[2 * N], tot[N], hei[N], cnt = 0, sz = S;
	void init(){
		for(int i = 1; i <= n; i++) rk[i] = s[i], tot[rk[i]]++;
		for(int i = 1; i <= S; i++) tot[i] += tot[i - 1];
		for(int i = n; i >= 1; i--) sa[tot[rk[i]]--] = i;
	}
	void bucsort(){
		for(int i = 0; i <= sz; i++) tot[i] = 0;
		for(int i = 1; i <= n; i++) tot[rk[i]]++;
		for(int i = 1; i <= sz; i++) tot[i] += tot[i - 1];
		for(int i = n; i >= 1; i--) sa[tot[rk[sec[i]]]--] = sec[i], sec[i] = 0;
	}
	void Sa(){
		init();
		for(int k = 1; k <= n; k <<= 1, cnt = 0){
			for(int i = n - k + 1; i <= n; i++) sec[++cnt] = i;
			for(int i = 1; i <= n; i++)
				if(sa[i] > k) sec[++cnt] = sa[i] - k;
			bucsort();
			for(int i = 1; i <= n; i++) rk1[i] = rk[i];
			sz = rk[sa[1]] = 1;
			for(int i = 2; i <= n; i++){
				if(rk1[sa[i]] == rk1[sa[i - 1]] && rk1[sa[i] + k] == rk1[sa[i - 1] + k]) rk[sa[i]] = sz;
				else rk[sa[i]] = ++sz;
			}
			if(sz == n) break;
		}
	}
	void height(){
		int k = 0;
		for(int i = 1; i <= n; i++){
			if(rk[i] == 1) continue;
			if(k) k--;
			int pos = sa[rk[i] - 1];
			while(pos + k <= n && i + k <= n && s[pos + k] == s[i + k]) k++;
			hei[rk[i]] = k;
		}
	}
}P;

标签:后缀,height,int,数组,SA,sa,rk
From: https://www.cnblogs.com/Peng1984729/p/18198753

相关文章

  • Codeforces 959B Mahmoud and Ehab and the message 题解
    题目简述小A想要给他的朋友小B发送了一条有$m$个单词的消息。他们的语言由编号从$a_1$到$a_n$的$n$个单词组成。一些单词具有相同的意思,因此存在$k$个单词组,其中每个组中的所有单词具有相同的意思。小A知道第$i$个单词可以以成本$m_i$发送。对于他的每个消息......
  • [USACO10OCT] Lake Counting S
    传送锚点:https://www.luogu.com.cn/problem/P1596由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个\(N\timesM(1\leqN\leq100,1\leqM\leq100)\)的网格图表示。每个网格中有水(W)或是旱地(.)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约......
  • Codeforces 1113B Sasha and Magnetic Machines 题解
    题目简述有一个长度为$n$的正整数序列。你可以对这个数列进行最多$1$次的如下操作:选择两个数$i$和$j$,其中$1\leqi,j\leqn$并且$i\neqj$,并选择一个可以整除$a_i$的正整数$x$,然后将$a_i$变为$\frac{a_i}{x}$,将$a_j$变为$a_j\cdotx$。问你操作后,该序......
  • 【jmeter】.SampleException: Mismatch between expected number of columns: 生成报
    1、问题现象Causedby:org.apache.jmeter.report.core.SampleException:Consumerfailedwithmessage:Consumerfailedwithmessage:Mismatchbetweenexpectednumberofcolumns:17andcolumnsinCSVfile:3,checkyourjmeter.save.saveservice.*configurationor......
  • 2.3.1---加入transaction
    transaction概念:可以简单地将transaction理解为一个包,在不同的验证平台中的transaction也不相同。一个简单的transaction如下:在这些代码中,其中dmac是48bit的以太网目的地址,smac是48bit的以太网源地址,ether_type是以太网类型,pload是其携带的数据大小,通过pload_cons约束可以看到......
  • P1668 [USACO04DEC] Cleaning Shifts S
    原题链接题解1.朴素想法,每头牛要么值班要么不值班,搜索遍历所有情况\(O(2^n)\)2.稍作修改,如果一头牛值班,那么在它值班结束时间之前值班的牛的数量一定是最优的,\(o(nT)\)3.换个思路,已知要覆盖\([1,T]\)这个时间段,所以左端点为\(1\)的牛必须选一个,且选右端点最大的那个,设这......
  • python 对于实现rsa加密算法
    importbase64importrsaclassGenerateKey(object):d="ascii"defgenerate_keys(self,bits=1024):(pubkey,privkey)=rsa.newkeys(bits)pem_pubkey=rsa.PublicKey.save_pkcs1(pubkey).decode(self.d)b64_pubkey......
  • js 判断数组中的所有值是否相同
    使用Set数据结构:将数组转换为Set,如果Set的长度为1,则说明数组中所有的值都相同。使用for循环:遍历数组,将每个元素与前面的元素进行比较,如果存在不同的元素,则说明数组中的所有值不相同。使用Array.prototype.every()方法:使用every方法遍历数组,判断数组中的每个元素是否......
  • springboot怎么将List集合数据转成JSON数组
    SpringBoot默认使用Jackson框架将Java对象转换成JSON格式。要转换List集合数据为JSON数组,可以采用以下两种方法:1.使用@ResponseBody注解在SpringBoot中,可以使用@ResponseBody注解标注要返回的List集合数据,让Spring自动将其转换成JSON数组。例如:@GetMapping("/list")@Respo......
  • 数据分享|SAS与eviews用ARIMA模型对我国大豆产量时间序列预测、稳定性、白噪声检验可
    全文链接:http://tecdat.cn/?p=31480最近我们被客户要求撰写关于ARIMA的研究报告,包括一些图形和统计输出。我国以前一直以来都是世界上大豆生产的第一大国。但由于各国的日益强大,导致我国豆种植面积和产量持续缩减。因此,预测我国的大豆产量对中国未来的经济发展有着极其重要的作......