首页 > 其他分享 >SA & SAM-dyx

SA & SAM-dyx

时间:2024-08-13 16:38:49浏览次数:14  
标签:dyx OI SAM SA rk sa 字典

SA & SAM

事先说明:以下所有字符串的下标从1开始


SA

[OI-WIKI链接](后缀数组简介 - OI Wiki)

是什么

SA要干的是这样一件事:

有一个字符串s,维护s每个后缀的字典序排名

也就是说:我们要对每个 \(1\le i\le n\) ,将 \(s[i,n]\) 按照字典序进行排序,

得到两个数组 \(sa\) 和 \(rk\)

其中

\(sa_i\) 表示字典序排名第 \(i\) 个的后缀的左端点

\(rk_i\) 表示 \(s[i,n]\) 这个后缀在所有后缀中的字典序排名

这也是SA中最重要的两个数组

引入一张OI-WIKI的图:

image-20240807200517471

然后这两个数组还有两个性质:

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

那么如何做SA呢?

怎么做

这里给出一种 \(O(nlog^2n)\) 的倍增做法,其实还有更快的 \(O(nlogn)\) 和 \(O(n)\) 做法,但似乎 \(O(nlog^2n)\) 就够用了 (OI-WIKI说的)

还是一张OI-WIKI的图

image-20240807201211160

过程:

  1. 将每个 \(s[i,i]\) ,也就是每个 \(s[i]\) 按照字典序排序,得到第一层的 \(sa\) 和 \(rk\)

  2. 将每个 \(s[i,i+1]\) ,也就是每两个字符组成的子串按照字典序排序,注意到这时rk数组代表了每个字符的字典序大小,所以我们可以将 \(s[i,i+1]\) 分成 \(s[i,i]\) 和 \(s[i+1,i+1]\) 两部分,用 \(rk\) 数组来排序:如果 \(rk[i]=rk[j]\) ,那么比较 \(rk[i+1]\) 和 \(rk[j+1]\) ,否则比较 \(rk[i]\) 和 \(rk[j]\) (这就是cmp过程)。这样我们就可以得到第二层的 \(sa\) 和 \(rk\)

    (插一句话:我们要相信世间人人以真诚相待,美好永存)

  3. 将每个 \(s[i,i+3]\) ,也就是每四个字符组成的子串按照字典序排序,这时我们依旧可以仿照2中的方法,将 \(s[i,i+3]\) 分成 \(s[i,i+1]\) 和 \(s[i+2,i+3]\) 两部分,通俗一点讲就是把长度为4的子串拆成两个长度为2的子串,由于我们已知第二层的 \(rk[i]\) 和 \(rk[i+2]\) ,也就是长度为2的子串的字典序排名,然后用 \(rk[i],rk[j],rk[i+2],r[j+2]\) 来排序:如果 \(rk[i]=rk[j]\) ,那么比较 \(rk[i+2]\) 和 \(rk[j+2]\) ,否则比较 \(rk[i]\) 和 \(rk[j]\) (感觉和分治很像,先把左右两个区间处理好,再处理当前区间)

​ ...

就这样一直到算到有一个数 \(k\) ,使得 \(1+2^k>n\) 为止 ,这样就算出了最终的sa和rk

为什么

那么SA可以用来干什么呢?

(可移步OI-WIKI)

  1. 求一个字符串循环位移的字典序排序(最小的循环位移不就是最小表示法嘛,\(O(n)\) 求就行了)
  2. 从字符串首尾取字符最小化字典序

height数组

\(height[i]=lcp(s[sa[i],n],s[sa[i-1],n])\)

就是排名第 \(i\) 个的后缀和它前一名的后缀的最长公共前缀

有一个结论:\(height[rk[i]]\ge height[rk[i-1]]-1\)

(不会证,懒得证,复习的我看过来,补一下这里)

然后就可以根据这个结论 \(O(n)\) 求 \(height\)

用处可移步OI-WIKI

SAM

。。。

下面引入一段对话来证明SAM的有用程度

那么SAM有什么用呢?

用处很多。

那么SAM可以用来做什么呢?

多了去了,等你看到题就知道了。

标签:dyx,OI,SAM,SA,rk,sa,字典
From: https://www.cnblogs.com/Lumos-Frappuccino/p/18357245

相关文章

  • D42 2-SAT+二进制枚举 P3825 [NOI2017] 游戏
    视频链接: P3825[NOI2017]游戏-洛谷|计算机科学教育新生态(luogu.com.cn)//2-SAT+二进制枚举O(2^8*(n+m))#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;constintN=100005;inthead[N],to[N<<1],ne[N<<1],idx;......
  • GameSalad-IOS-游戏开发学习手册-全-
    GameSaladIOS游戏开发学习手册(全)原文:LearnGameSaladforiOSGameDevelopmentforiPhone,iPad,andHTML5协议:CCBY-NC-SA4.0零、简介2007年,苹果推出了iPhone,彻底改变了我们的生活方式,但最重要的是iOS的诞生。今天,iOS被用于iPhone、iPad和iPodTouch。通过A......
  • leensa邀请码
    #leensa邀请码https://leensc.com/#/register?code=XGn78xbMhttps://leensc.com/#/register?code=TKhSrP4khttps://leensc.com/#/register?code=xReWkJi2#leensa邀请码#定义函数来执行加法defadd(x,y):returnx+y#定义函数来执行减法defsubtract(x,......
  • P5836 [USACO19DEC] Milk Visits S(树上并查集)
    核心思路对于相同颜色且相邻的点合并。若不在同一集合,则0若在同一集合,同色1异色0AC代码#include<bits/stdc++.h>usingnamespacestd;intfa[1145141];charcol[1145141];intn,m;intfind(intx){ if(x==fa[x]) returnx; returnfa[x]=find(fa[x]);}v......
  • mysql: Usage权限
    一,Usage权限的功能1,官方的解释可以看到官方的说明:无权限,只允许连接到数据库2,Usage是连接(登陆)权限,当建立一个用户时,就会自动授予其usage权限(默认授予)。该权限只能用于数据库登陆,不能执行任何操作;且usage权限不能被回收,也即REVOKE用户并不能删除用户。 二,测试:创建用户后......
  • hdu7462-字符串【SAM,二分】
    正题题目链接:https://acm.hdu.edu.cn/showproblem.php?pid=7462题目大意你有一个由\(a,b\)组成的字符串\(s\)。有\(m\)个操作:询问有多少个本质不同的串\(t\)使得\(s[l,r]\)是\(t\)的子串且两个串在\(s\)中的出现次数相同。询问有多少个本质不同的串\(t\)......
  • 百诺教育-ASA防火墙-2
    1.1asa实验环境简介1.1.1物理拓扑图1.1.2逻辑拓扑图1.2各设备初始化配置sw:vlan2nameinsidevlan3namedmzvlan4nameoutsideintrangef0/1-2swmoaccswaccvlan2interfacef0/3swtrunkendot1qswmodetrunkintf0/4swmoaccswaccvlan3int......
  • 【题解】 [USACO 2007 FEB] Cow Party S
    题目描述题目大意给定一个有向图,以及一个顶点。求其他所有点到给定点,再从给定点回到各自起始点的最短路中的最大值。思路本题主要考查:对单源最短路算法的熟练运用。最短路总共分为2段:其他所有点到给定点、给定点回到各自起始点。首先求第一段:可以在原图的基础上建一个反向图......
  • Rounding necessary错误解决Java的BigDecimal除法的
    出现Roundingnecessary错误原因是使用了BigDecimal的setScale方法导致。错误原因:setScale方法保留小数位数小于实际位数并且未指定roundingMode参数即报错。如下代码:BigDecimalrs=newBigDecimal("2057.9200");rs.setScale(2);上述代码实际数值是2057.9200是4位小......
  • [算法] 2-SAT简记
    真的是简记2-SAT$2-SAT$用于求解一个变量只有两种情况的适应性问题(就是有没有解以及输出一种方案);其实可以类比二分图最大匹配(但其实两者的差别还是很大的);算法流程对于每一个变量,我们都有两种情况,$true$和$false$;而题目中给我们的,是形如{$A=true/false$或......