后缀数组
#define SUFFIX_ARRAY_PFXDBL
#ifdef SUFFIX_ARRAY_PFXDBL
namespace SA{
/*
Suffix Array, Prefix Doubling Method
<SUBSCRIPT_START_FROM,SIZE>
MAXN : Maximum length for string
s : String for building suffix array <0,MAXN>
t,t2,c : [Auxiliary] buffers <0,MAXN>
n : Length of string
sa : Suffix Array, Lexicographically ith suffix starts from. <0,MAXN>
rank : Suffix Rank, rank of the suffix starts from i <0,MAXN>
height : LCP of suffix starts from sa[i] and sa[i-1] <1,MAXN>
build_sa(int m) : m is the size of character set("character" being 0~m-1), should set s and n previously.
getHeight() : Calculate height and rank array accordingly.
#define REP(i,t) for(int i = 0;i < t; i++)
#define REP_R(i,t) for(int i = t-1;i >= 0; i--)
#define REP_1(i,t) for(int i = 1;i <= t; i++)
#define REP_1R(i,t) for(int i = t;i >= 1; i--)
Time : O(nlogn)
Space : 7n
*/
const int MAXN = 10005;
char s[MAXN];
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],rank[MAXN],height[MAXN],n;
void build_sa(int m){
int *x = t,*y = t2;
//第一次基数排序
REP(i, m) c[i] = 0; //重置排序数组
REP(i, n) c[x[i]=s[i]]++; //拷贝字符串内容到x缓冲区,并在基数排序数组中统计字符数量
REP_1(i, m-1) c[i] += c[i-1]; //基数排序数组求前缀和以算出排名
REP_R(i, n-1) sa[--c[x[i]]] = i; //从后往前顺次查询后缀的排名写入SA(字符相同的时候,长度小的靠前,长度大的靠后)
//此时的x数组可以看成是保存了各个位置开始的后缀对应的第一基准
for(int k = 1;k <= n; k <<= 1){
//第k次基数排序,单组长度2^k
int p = 0;
//利用SA排序第二基准,y存储的是第二基准排序之后的后缀开始位置
for(int i = n-k;i < n; i++) y[p++] = i; //长度没达到k,这种只能看第一基准,第二基准视为0
REP(i, n) if(sa[i] >= k) y[p++] = sa[i]-k; //从前往后扫SA,即从字典序小的后缀开始扫,如果这个后缀的开始位置>=k的话,
//这个后缀在sa中的结果实际上是i-k的第二基准
//排序第一基准
REP(i, m) c[i] = 0; //重置排序数组
REP(i, n) c[x[y[i]]]++; //按第二基准顺序读取第一基准进行统计
REP(i, m) c[i] += c[i-1];//基数排序数组求前缀和以算出排名
REP_R(i, n-1) sa[--c[x[y[i]]]] = y[i];//按第二基准从后往前顺次查询后缀的排名写入SA
//准备下一次排序的第一基准序列x
//第二基准排序结果y没有用了,上一次的第一基准序列x还有用,直接互换
swap(x, y);
//现在y是上一次的第一基准序列
p = 1;
x[sa[0]] = 0;//第一基准从0开始
//现在的sa是排好序的,从小到大查询,如果两项无法分出先后,就令成统一基准,否则基准自增
//如果两个后缀的第一关键字和第二关键字一样,说明他们的排名一样
REP_1(i, n-1) x[sa[i]] = ((y[sa[i-1]] == y[sa[i]]) && (y[sa[i-1]+k]==y[sa[i]+k]))? p-1 : p++;
if(p >= n) break; //如果基准数已达n,说明排序完成,所有后缀已经分出先后
m = p; //下一轮排序的基准数是p
}
}
void getHeight(){
int i,j,k = 0;
REP(i, n) rank[sa[i]] = i;
for(i = 0;i < n; height[rank[i++]] = k)
for(k?k--:0,j = sa[rank[i]-1];s[i+k]==s[j+k];k++);
return;
}
}
#endif
┆ 凉 ┆ 暖 ┆ 降 ┆ 等 ┆ 幸 ┆ 我 ┆ 我 ┆ 里 ┆ 将 ┆ ┆ 可 ┆ 有 ┆ 谦 ┆ 戮 ┆ 那 ┆ ┆ 大 ┆ ┆ 始 ┆ 然 ┆
┆ 薄 ┆ 一 ┆ 临 ┆ 你 ┆ 的 ┆ 还 ┆ 没 ┆ ┆ 来 ┆ ┆ 是 ┆ 来 ┆ 逊 ┆ 没 ┆ 些 ┆ ┆ 雁 ┆ ┆ 终 ┆ 而 ┆
┆ ┆ 暖 ┆ ┆ 如 ┆ 地 ┆ 站 ┆ 有 ┆ ┆ 也 ┆ ┆ 我 ┆ ┆ 的 ┆ 有 ┆ 精 ┆ ┆ 也 ┆ ┆ 没 ┆ 你 ┆
┆ ┆ 这 ┆ ┆ 试 ┆ 方 ┆ 在 ┆ 逃 ┆ ┆ 会 ┆ ┆ 在 ┆ ┆ 清 ┆ 来 ┆ 准 ┆ ┆ 没 ┆ ┆ 有 ┆ 没 ┆
┆ ┆ 生 ┆ ┆ 探 ┆ ┆ 最 ┆ 避 ┆ ┆ 在 ┆ ┆ 这 ┆ ┆ 晨 ┆ ┆ 的 ┆ ┆ 有 ┆ ┆ 来 ┆ 有 ┆
┆ ┆ 之 ┆ ┆ 般 ┆ ┆ 不 ┆ ┆ ┆ 这 ┆ ┆ 里 ┆ ┆ 没 ┆ ┆ 杀 ┆ ┆ 来 ┆ ┆ ┆ 来 ┆

浙公网安备 33010602011771号