/*
problem: jzoj1598(詢問乙個字串中有多少至少出現兩次的子串)
content: sa's code and explanation
author : anoyer
*/#include
#include
#include
#include
using namespace std;
const
int maxn =
100005
;char ch[maxn]
, all[maxn]
;int sa[maxn]
, rank[maxn]
, height[maxn]
, tax[maxn]
, tp[maxn]
, a[maxn]
, n, m;
char str[maxn]
;//rank[i] 第i個字尾的排名; sa[i] 排名為i的字尾位置; height[i] 排名為i的字尾與排名為(i-1)的字尾的lcp
//tax[i] 計數排序輔助陣列; tp[i] rank的輔助陣列(計數排序中的第二關鍵字),與sa意義一樣。
//a為原串
void
rsort()
//計數排序,把新的二元組排序。
intcmp
(int
*f,int x,
int y,
int w)
//通過二元組兩個下標的比較,確定兩個子串是否相同
void
suffix()
//離散:把相等的字串的rank設為相同。
//lcp
int j, k =0;
for(
int i =
1; i <= n; height[rank[i ++]]
= k)
for( k = k ? k -
1: k, j = sa[rank[i]-1
]; a[i + k]
== a[j + k]
;++ k)
;//這個知道原理後就比較好理解程式
}void
init()
intmain()
/*int ans = height[2];
for (int i = 3; i <= n; i ++) ans += max(height[i] - height[i - 1], 0);
printf("%d\n", ans); */
}
字尾陣列 da演算法
sa陣列,他儲存1.n 的某個排列,sa 2 sa n 並且保證 suffix sa i suffix sa i 1 1 i 也就是將 s 的 n 個字尾從小到大進行排序之後把排好序的字尾的開頭位置順次放入 sa 中。rank陣列,他儲存的是每個位置的字尾子串的排名,與sa陣列是可以互逆的。heig...
字尾陣列 模板
char s n 陣列的長度要為兩倍的 int n n全域性變數為字元陣列的長度的 int sa n 2 high n 2 rank n 2 tmp n 2 top n 2 void makesa void lcp int main gets s int len strlen s s len get...
字尾陣列模板
過了期末了,繼續寫acm題 自己寫的字尾陣列模板。k,len,rank,sa,tmp,都要寫在外面,這樣就不用來回折騰了。也是使用倍增法來做的,得到乙個sa,儲存了字尾排在第i位的字尾的起始位置。因為空也算乙個字尾,所以函式中都是 len include include include includ...