[学习笔记]后缀相关算法
SA
SA实际上求出两个数组
满足其性质
这里仅给出一个
其他做法参见
点击查看代码
bool cmp(int i,int j){
if(rk[i]!=rk[j]){
return rk[i]<rk[j];
}else{
int ri,rj;
ri=i+k<n?rk[i+k]:-1;
rj=j+k<n?rk[j+k]:-1;
return ri<rj;
}
}
void calc(){
for(int i=0;i<n;i++){
rk[i]=s[i];
sa[i]=i;
}
for(k=1;k<n;k*=2){
sort(sa,sa+n,cmp);
tmp[sa[0]]=0;
for(int i=0;i<n-1;i++){
tmp[sa[i+1]]=tmp[sa[i]]+cmp(sa[i],sa[i+1]);
}
for(int i=0;i<n;i++){
rk[i]=tmp[i];
}
}
}
很多情况下我们都要求出辅助数组
其有引理
所以根据该引理,维护一个指针即可
点击查看代码
for (i = 1, k = 0; i <= n; ++i) {
if (rk[i] == 0) continue;
if (k) --k;
while (s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
height[rk[i]] = k;
}
其应用大概有:
两个子串最长公共前缀
不同子串数目
连续的相同子串([NOI2016] 优秀的拆分):
考虑枚举长度然后设置关键点。
若存在
配合图食用。
搭配其他数据结构
略。
SAM
SAM是一个接受字符串
其也是对于将所有子串插入trie里的trie图压缩的结果。
子串的性质
一些概念和性质
结束位置 endpos
考虑字符串的任意非空子串,我们记
考虑按
显然,
引理1:字串两个子串为
, ,其 相同,长度小的总为长度长的后缀。
引理2:每个等价类的元素子串的长度连续,且后缀关系传递。
后缀链接
考虑
我们设
引理3:所有后缀链接构成一颗根节点为
的树,其上子节点的 是父节点的 的子集。
后缀自动机建法
考虑增量建法。
考虑已经维护了
点击查看代码
ll nod = 1,lst = 1;
inline void insert(int c){
int p = lst,q = ++nod;lst = q;
len[q] = len[p] + 1,f[q] = 1;
while(!ch[p][c] && p != 0){//向上找
ch[p][c] = q;
p = link[p];
}
if(p == 0)
link[q] = 1;
else{
int x = ch[p][c];
if(len[p] + 1 == len[x]){
link[q] = x;
}else{
int y = ++ nod ;//复制一个新节点
link[y] = link[x];
link[x] = link[q] = y;
len[y] = len[p] + 1;
std::memcpy(ch[y],ch[x],sizeof(ch[x]));
while(p != 0 && ch[p][c] == x){
ch[p][c] = y;
p = link[p];
}
}
}
}
本文作者:fhq_treap
本文链接:https://www.cnblogs.com/dixiao/p/15936062.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2021-02-25 CF618F Double Knapsack
2021-02-25 【BZOJ 4668 冷战】