后缀数组
后缀排序
char s[N];
int n,sa[N],rk[N],ork[N<<1];
int buc[N],id[N],pid[N];
bool cmp(int a,int b,int w){return ork[a]==ork[b] && ork[a+w]==ork[b+w];}
void build()
{
int m=(1<<17),p=0;
for(int i=1; i<=n; i++) buc[rk[i]=s[i]]++;
for(int i=1; i<=m; i++) buc[i]+=buc[i-1];
for(int i=n; i>=1; i--) sa[buc[s[i]]--]=i;
for(int w=1; ; w<<=1,m=p,p=0)
{
for(int i=n; i>n-w; i--) id[++p]=i;
for(int i=1; i<=n; i++) if(sa[i]>w) id[++p]=sa[i]-w;
for(int i=0; i<=m+1; i++) buc[i]=0;
for(int i=1; i<=n; i++) buc[pid[i]=rk[id[i]]]++;
for(int i=1; i<=m; i++) buc[i]+=buc[i-1];
for(int i=n; i>=1; i--) sa[buc[pid[i]]--]=id[i];
for(int i=1; i<=n; i++) ork[i]=rk[i];
p=0;
for(int i=1; i<=n; i++) rk[sa[i]]=cmp(sa[i-1],sa[i],w)? p:++p;
if(p==n) break;
}
}
求 数组
关键性质:
int k=0;
for(int i=1; i<=tot; i++)
{
if(k) k--;
while(s[i+k]==s[sa[rk[i]-1]+k]) k++;
h[rk[i]]=k;
}
应用
1、求任意两个后缀的 LCP
2、求本质不同的子串个数
3、与单调栈结合
将
考虑按
一些题目
CF822E Liar
考虑朴素 DP,设
P2178 [NOI2015] 品酒大会
因为是
P5341 [TJOI2019] 甲苯先生和大中锋的字符串
使用 SA 分析字符串的常见方式:将字符串按照
我们在排序后的字符串取出一个长度为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
2023-08-25 博弈论小记
2023-08-25 欧拉路径回顾
2023-08-25 2023.8.25测试