后缀数组
先介绍计数排序。思考一下桶排序,桶排序是不稳定的。计数排序相当于是稳定的桶排序,时间复杂度为
设数组
正确性:假设有若干个
接下来进入正题,介绍后缀数组。下文默认字符串下标从
后缀数组涉及三个数组:
然后先求
第一步:将所有后缀按照第一个字母稳定地排序(利用计数排序)
for(int i=1;i<=n;i++) c[x[i]=s[i]]++;
//这里由于字符集不大,所以桶的大小直接开成字符集大小,离散化按照字符离散化
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[x[i]]--]=i;
第二步:假设我们已经对所有后缀按照前
外层循环:for (int k = 1; k <= n; k <<= 1)
我们先按照所有后缀的第
先进行第一次排序:
对于
int num = 0;
for (int i = n - k + 1; i <= n; i ++ ) y[ ++ num] = i;
对于
for (int i = 1; i <= n; i ++ )
if (sa[i] > k) y[ ++ num] = sa[i] - k;
再进行第二次排序:
首先按照前
for (int i = 1; i <= m; i ++ ) c[i] = 0;
for (int i = 1; i <= n; i ++ ) c[x[i]] ++ ;
for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];
for (int i = n; i; i -- ) sa[c[x[y[i]]] -- ] = y[i];
然后将
swap(x, y);
然后更新
x[sa[1]] = 1, num = 1;
for (int i = 2; i <= n; i ++ )
if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])
x[sa[i]] = num;
else x[sa[i]]=++num;
注意y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]
是不会越界的,因为
最后,如果离散化值域达到了
if (num == n) break;
m = num;
上述倍增法的时间复杂度为
求
补充一个
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构