后缀数组是什么?可以吃吗?
不可以吃,它是给一个字符串的所有后缀进行排序的算法。
如:一个字符串aabaaaab,它的后缀排好序后起始位置分别是:4 5 6 1 7 2 8 3
显然如果暴力去排序时间复杂度为O(n2),可以用倍增算法或DC3算法来解决,本文主要介绍倍增算法(我才不会告诉你其实是我不会DC3算法呢)。
接下来定义如下几个数组:
数组名 | 意义 |
---|---|
sai | 原串S拍好序后第i个后缀的开头位置(就是排第几的是谁) |
ranki | 开头为i的后缀的名次(就是谁排第几) |
引用大佬图解:
倍增法的主要内容?
每次对长度为2k的串进行排序时都可以利用两个连续的长为2k−1的串排序的结果来进行排序,当2k>=n时,每个串都是以这个串的起点为起点的后缀。
再次引用大佬图解:
这张图是什么意思呢?
就是:x和y分别作为第一关键字和第二关键字,进行排序,以这一次排序的结果作为下一次排序的参考。
怎么排序?
需要排序的范围不超过n,当然是选择计数排序(基数排序,桶排序)啊。
时间复杂度?
O(nlogn),如果不使用计数排序就是O(nlog2n)
代码
温馨提示:复制到记事本上并将tab键调成8格效果更佳
#include
#include
int sa[(maxn<<1)&#43;10],rank[(maxn<<1)&#43;10],tmp[(maxn<<1)&#43;10];
int sum[(maxn<<1)&#43;10],a[(maxn<<1)&#43;10],n;inline int swap(int *&x,int *&y)//指针swap
{int *t&#61;x;x&#61;y;y&#61;t;return 0;
}inline int suffix_sort()
{int *x&#61;rank,*y&#61;tmp,m&#61;26;//先排序for(register int i&#61;1; i<&#61;n; &#43;&#43;i){x[i]&#61;a[i];y[i]&#61;i;&#43;&#43;sum[x[i]];}for(register int i&#61;1; i<&#61;m; &#43;&#43;i){sum[i]&#43;&#61;sum[i-1];}for(register int i&#61;n; i; --i){sa[sum[x[i]]]&#61;i;--sum[x[i]];}int len&#61;1,p&#61;1;while(p
}int main()
{scanf("%s",s&#43;1);n&#61;strlen(s&#43;1);for(register int i&#61;1; i<&#61;n; &#43;&#43;i){a[i]&#61;s[i]-&#39;a&#39;&#43;1;}suffix_sort();for(register int i&#61;1; i<&#61;n; &#43;&#43;i){printf("%d\n",sa[i]);}return 0;
}