后缀数组(SA)
后缀数组(SA)
并非指数字的后缀,而针对字符串而生的算法。
字符串的后缀指是指从某个位置开始到整个串末尾结束的一个特殊子串。
后缀排序#
将所有后缀按照字典序排序,利用计数排序时间+倍增复杂度为
倍增排序示意图:
先求出
height 数组#
height 数组的定义#
引理#
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 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;
}
}
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) {height(); break;}
}
}
}P;
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库