\(sa[i]=j\),表示從小到大排好的字尾中,第\(i\)小的字尾是字尾\(j\)(開頭為\(j\)的字尾)。
\(\rule[-10pt]\)
\(rk[i]=j\),表示字尾\(i\)(開頭為\(i\)的字尾)的排名為\(j\)(從小到大)。
簡單的說,字尾陣列是「排第幾的是誰?」,名次陣列是「你排第幾?」。兩者為互逆運算。
\(\rule[-10pt]\)
\(height[i]=lcp(i,i-1)\),\(lcp(i,i-1)=lcp(sa[i],sa[i-1])\)。
\(lcp\)為最長公共字首,則\(height\)陣列的定義為排名相鄰的兩個字尾的最長公共字首。
\(\rule[-10pt]\)
假設兩個字尾分別為\(i,j\),且\(rk[i]。
則\(lcp(i,j)=height[rank[i]+1],
height[rank[i]+2], height[rank[i]+3], … ,height[rank[j]]\)中的最小值,轉換為rmq問題即可。
\(\rule[-10pt]\)
時間複雜度:\(o(n)\),空間常數較大。
#include #include #include #define f(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define g(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
using namespace std;
const int n = 3*(1e5+5);
int wa[n], wb[n], ws[n], wv[n], sa[n];
int rak[n], height[n], cal[n],n;
char s[n],ans[n],s1[n];
int cnt[n];
int c0(int *r, int a, int b)
int c12(int k, int *r, int a, int b)
void rsort(int *r, int *a, int *b, int n, int m)
void dc3(int *r, int *sa, int n, int m)
void calheight(int *r, int *sa, int n)
int main() puts("");
}return 0;
}
時間複雜度:\(o(nlogn)\),空間複雜度較小。
#includeusing namespace std;
typedef long long ll;
const int n=100010;
int wa[n],wb[n],wv[n],wss[n],rak[n],height[n],cal[n],n,sa[n];
char s[n];
int cmp(int *r,int a,int b,int l)
void da(int *r,int *sa,int n,int m)
return;
}void calheight(int *r,int *sa,int n)
int main()puts("");
for(int i=1;i<=n;i++) puts("");
for(int i=1;i<=n;i++) puts("");
}}
字尾陣列 模板
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...
模板 字尾陣列
include include includeusing namespace std const int max 20001 int num max int sa max rank max height max int wa max wb max wv max wd max int cmp int ...