首页 > 其他分享 >SA SAM

SA SAM

时间:2024-11-11 22:30:33浏览次数:1  
标签:SAM text pos len mx link SA operatorname

发现很久不写字符串所有模板都忘了,还是要复习一遍。

SA

后缀排序

令 \(sa_{i}\) 表示排名为 \(i\) 的后缀编号,\(rk_i\) 表示后缀 \(s[i:n]\) 的排名。有两种求法:

  • 朴素倍增,时间复杂度 \(\mathcal O(n\log^2 n)\)。

每次更新两个关键字,暴力 sort,重新编号 \(sa\)。

  • 基数排序,时间复杂度 \(\mathcal O(n\log n)\)。

令 \(x_i\) 表示编号为 \(i\) 后缀的第一关键字,\(y_i\) 表示第二关键字排名为 \(i\) 的后缀的编号。

for (int i = 1; i <= n; i ++) cnt[x[i] = s[i]] ++;
for (int i = 2; i <= m; i ++) cnt[i] += cnt[i - 1];
for (int i = 1; i <= n; i ++) sa[cnt[x[i]] --] = i;

/* 对 sa[] 赋初值 */

for (int k = 1; k <= n; k <<= 1) {
	int tot = 0;
	for (int i = n - k + 1; i <= n; i ++) y[++ tot] = i;
	for (int i = 1; i <= n; i ++) if (sa[i] > k) y[++ tot] = sa[i] - k;
	
    // 求出 y[]。
    // 因为 [n - k + 1, n] 没有第二关键字(就是 0),所以先排在前面。
    // 枚举第二关键字 i,如果有对应的第一关键字,放入数组。
    
	for (int i = 1; i <= m; i ++) cnt[i] = 0;
	for (int i = 1; i <= n; i ++) cnt[x[i]] ++;
	for (int i = 2; i <= m; i ++) cnt[i] += cnt[i - 1];
	// 对第一关键字排序。
    
    for (int i = n; i >= 1; i --) sa[cnt[x[y[i]]] --] = y[i];
    // 因为第一关键字相同按第二关键字,所以从大往小枚举第二关键字,这样保证能正确排序(这里注意赋值是编号 x[i])。
    
	for (int i = 1; i <= n; i ++) rx[i] = x[i];
    // 存副本,更新。

	x[sa[1]] = 1, tot = 1;
	for (int i = 2; i <= n; i ++) {
		int nw = sa[i], lst = sa[i - 1];
		if (rx[nw] == rx[lst] && rx[nw + k] == rx[lst + k])
			x[nw] = tot; else x[nw] = ++ tot;
	}
    
    // 如果两个关键字都对应相等,则为相同排名。
	
	m = tot;
    // 更新桶大小。
}

height 数组

令 \(\operatorname{LCP}(i,j)\) 为 \(s[i:n]\) 和 \(s[j:n]\) 的最长公共前缀,\(\operatorname{height}_{i}\) 表示 \(\operatorname{LCP}(sa_{i-1},sa_i)\)。有个很明显的结论:\(\operatorname{LCP}(i,j)=\min\limits_{k=rk_i+1}^{rk_j}\{\operatorname{height}_{k}\}\)(LCP Theorem)。

我们再引出 \(h_{i}\) 表示 \(\operatorname{height}_{rk_i}\),引申出了一个结论为 \(h_i\ge h_{i-1}-1\),可以看图一。

\[[\text{pic 1}] \]

我们发现从 \(k\rightarrow k+1\) 和 \(i-1\rightarrow i\) 刚好是去掉首字母。对于 \(s[k:n]\) 和 \(s[i-1:n]\) 首字母相同的情况,则 \(\operatorname{LCP}(k+1,i)=h_{i-1}-1\),根据 LCP Theorem,\(h_{i-1}-1\le h_i\);首字母不同,\(h_{i-1}=0\),必然成立。

时间复杂度 \(\mathcal O(n)\)。

for (int i = 1; i <= n; i ++) rk[sa[i]] = i;

int lst = 0;
for (int i = 1; i <= n; i ++) {
	if (rk[i] == 1) continue;
    
	int j = sa[rk[i] - 1]; lst = max(0, lst - 1);
	while(max(i, j) + lst <= n && s[i + lst] == s[j + lst]) lst ++;
	he[rk[i]] = lst;
}

应用

  • 不同子串个数

\(ans=\dfrac{n(n+1)}{2}-\sum\limits_{i}\operatorname{height}_i\)。

  • 最长公共子串

将所有字符串拼接在一起并用字符隔开,求出 \(sa,\operatorname{height}\) 数组,在 \(sa\) 上双指针求出能覆盖所有颜色的区间 \([l,r]\),答案即为 \(\max\{\operatorname{LCP}(l,r)\}\),用单调队列可做到 \(\mathcal O(n)\)。

SAM

以下我们研究都相对于字符串 \(s\)。

\(\textsf{endpos}\)

定义 \(\text{endpos}(r)\)(以下简写 \(\text{pos}(r)\))为 \(r\) 在 \(s\) 中出现的下标集合。

有以下性质:

  • 对于 \(\text{pos}(r)=\text{pos}(r')\) 且 \(|r|>|r'|\),有 \(r'\) 为 \(r\) 的后缀。
  • 对于 \(|r|\ge|r'|\),只有 \(\text{pos}(r)\subseteq \text{pos}(r')\) 或 \(\text{pos}(r)\cap \text{pos}(r')=\varnothing\)。
  • 对于同一个 \(\text{endpos}\) 等价类集合 \(s\),所有 \(\text{pos}(r)=S\) 的 \(r\) 组成的长度 \(|r|\) 集合,刚好为一个区间。

于是我们对于每种 \(\text{pos}\) 集合建一个点 \(x\),并将每个 \(s\) 的子串放到相应的点中,其中 \(\text{len}_{\max}(x)=\max |s'|\)(以下简写为 \(\text{len}(x)\)),其中对应的字符串为 \(\text{mx}(x)\)。

\(\textsf{link}\)

令 \(\text{link}(x)\) 表示 \(r=\text{mx}(x)\) 最长的后缀 \(r'\) 对应的节点,满足 \(\text{pos}(r')\not=\text{pos}(r)\)。

有以下性质:

  • 连接所有 \((\text{link}(x),x)\),形成一棵树。
  • \(\text{len}_{\min}(x)=\text{len}(\text{link}(x))+1\)。

构造 SAM

SAM 为在线构造,时间复杂度为 \(\mathcal O(n)\),令当前正在插入字符 \(c\)。

  • 令上一次的字符串为 \(s'\),对应的节点为 \(p\),则 \(s=s'+c\)。新建目前点为 \(np\)。
  • 有 \(\text{len}(np)=\text{len}(p)+1\),迭代 \(np\) 的 \(\text{link}\) 祖先,对于所有没有 \(c\) 边的节点可以将 \(c\) 边连向 \(np\)。
  • 决定 \(\text{link}(np)\)
    • 若所有祖先都没有 \(c\) 边,则 \(\text{link}(np)=0\)。
    • 否则讨论第一个祖先 \(fa\),\(c\) 边指向的节点 \(q\)。
      • 如果 \(\text{len}(fa)+1=\text{len}(q)\),说明 \(\text{mx}(fa)+c=\text{mx}(q)\),则所有在 \(q\) 中的字符串为 \(\text{mx}(fa)+c\) 的后缀,此时 \(\text{link}(np)=q\)。
      • 否则 \(\text{mx}(q)\) 并不是由 \(\text{mx}(fa)\) 产生的,我们将 \(q\) 拆成两部分(如图二),将属于 \(\text{mx}(fa)\) 产生的部分设为 \(\text{link}(np)\),和另一部分的 \(\text{link}\),并将剩余所有的祖先修改 \(c\) 边。

\[[\text{pic 2}] \]

struct SAM {
	int lst, tot, cnt[maxn << 1]; 
	SAM () { tot = lst = 1; }
	void ins(int c) {
		int p = lst, np = lst = ++ tot; g[np].mx = g[p].mx + 1, cnt[np] = 1;
		while (p && !g[p].ch[c]) g[p].ch[c] = np, p = g[p].fa;

		if (!p) g[np].fa = 1;
		else {
			int q = g[p].ch[c];
			if (g[q].mx == g[p].mx + 1) g[np].fa = q;
			else {
				int r = ++ tot; 
				g[r] = g[q], g[r].mx = g[p].mx + 1, g[q].fa = g[np].fa = r;
				while (p && g[p].ch[c] == q) g[p].ch[c] = r, p = g[p].fa;
			}
		}
	}

标签:SAM,text,pos,len,mx,link,SA,operatorname
From: https://www.cnblogs.com/notears/p/18540721

相关文章

  • PCL 点云分割 Ransac分割3D球体
    目录一、概述1.1原理1.2实现步骤1.3应用场景二、代码实现2.1关键函数2.1.1球体拟合2.1.2可视化2.2完整代码三、实现效果PCL点云算法汇总及实战案例汇总的目录地址链接:PCL点云算法与项目实战案例汇总(长期更新)一、概述        在点云数据处理中,RANSAC(随......
  • Autosar CP Can State Mangement规范导读
    CanSM的主要功能CAN网络通信模式控制管理CAN网络的启动、停止和不同通信模式(如全通信、静默通信、无通信)之间的切换。通过状态机实现对CAN网络状态的精确控制,确保网络在不同条件下稳定运行。错误处理与状态报告根据AUTOSAR基础软件的错误分类方案处理错误,包括......
  • 理解@Transactional
    在SpringBoot中,@Transactional注解仍然是Spring框架提供的一个核心注解,用于声明式事务管理。SpringBoot通过自动配置和简化配置,使得在SpringBoot应用程序中使用@Transactional注解变得更加方便。本文将深入探讨@Transactional注解在SpringBoot中的使用方法、......
  • Spring学习笔记_30——事务接口PlatformTransactionManager
    PlatformTransactionManager是Spring框架中事务管理的核心接口,它负责管理事务的创建、提交和回滚等操作。源码/**Copyright2002-2020theoriginalauthororauthors.**LicensedundertheApacheLicense,Version2.0(the"License");*youmaynotusethis......
  • Qualcomm SA8295P资源解析(一):驱动智能驾驶与车载娱乐的多接口技术先锋
    QualcommSA8295P的核心:多核CPU设计QualcommSA8295P的CPU采用了Kryo695架构,其分成了两种不同配置的核心组,分别是KryoGoldPrime和KryoGold核心。KryoGoldPrime核心带有1MB的L2缓存,最高频率可以达到2.38GHz,而KryoGold核心配备512KB的L2缓存,频率最高为2.09GHz。这......
  • apisampling.dll文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个apisampling.dll文件(挑选合适的版本文件)把......
  • P2949 【USACO09OPEN】 Work Scheduling G
    P2949[USACO09OPEN]WorkSchedulingG-洛谷|计算机科学教育新生态(luogu.com.cn)反悔贪心记录详情-洛谷|计算机科学教育新生态(luogu.com.cn)#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#definexfirst......
  • Sol - P2900 [USACO08MAR] Land Acquisition G
    完整准确地理解FlushHu的题解。0x00初步分析我们发现对于矩形\(i,j\)满足\(h_i\leqh_j,w_i\leqw_j\),那么选\(j\)的时候一定可以并购\(i\),因此将\(i\)删去。将剩下的矩形按照\(h\)从大到小排序,此时\(w\)从小到大。因为如果合并的不是一段连续区间,那么中间未被......
  • 2-sat小记
    记得好像写了,但找了一下发现没写,于是写一下2-sat用于求p→q的蕴含关系集合的一组解(或判断无解)流程:先构造蕴含关系集合,谁成立/不成立时另一个必须怎么样对每个命题p建p和非p(p'),每个蕴含关系p→q连边(p,q),(q',p'),一定要有逆否的反向边然后①跑tarjan缩点,若存在p和p'在同......
  • AUTOSAR CP Ethernet State Manager(EthSM)规范的主要功能以及工作原理导读
    AUTOSAREthernetStateManager(以下简称EthSM)规范的主要功能AUTOSAREthernetStateManager(以下简称EthSM)规范的主要功能包括:通信控制网络模式管理:为通信管理器(ComM)提供API,用于请求以太网网络的通信模式,如ETHSM_FULL_COMMUNICATION(全通信)、ETHSM_SILENT_COMMUNICATIO......