后缀树组(SA)初探
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后缀树组(SA)初探相关的知识,希望对你有一定的参考价值。
还没有什么任意两个后缀的LCP这些玩意儿。
启蒙题:输入一个串S,求最长的串T使得T在S中出现过不止一次。输出T的长度。
1 #include <algorithm> 2 #include <stdio.h> 3 #include <string.h> 4 #define N 100 5 char s[N+1]; 6 int n, sa[N], rank[N], height[N]; 7 namespace SABuilder { 8 int cnt[N], t1[N<<1], t2[N<<1]; 9 void work() { 10 int i, k, m = 26, p, *x = t1, *y = t2; 11 memset(cnt, 0, m * sizeof(int)); 12 for(i = 0; i < n; ++i) ++cnt[x[i] = s[i] - ‘a‘]; 13 for(i = 1; i < m; ++i) cnt[i] += cnt[i-1]; 14 for(i = n - 1; i >= 0; --i) sa[--cnt[x[i]]] = i; 15 for(k = 1; k <= n; k <<= 1) { 16 for(i = n-k, p = 0; i < n; ++i) y[p++] = i; 17 for(i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k; 18 memset(cnt, 0, m * sizeof(int)); 19 for(i = 0; i < n; ++i) ++cnt[x[y[i]]]; 20 for(i = 1; i < m; ++i) cnt[i] += cnt[i-1]; 21 for(i = n - 1; i >= 0; --i) sa[--cnt[x[y[i]]]] = y[i]; 22 std::swap(x, y); 23 x[sa[0]] = 0; 24 for(i = m = 1; i < n; ++i) { 25 x[sa[i]] = y[sa[i]]==y[sa[i-1]]&&sa[i]+k<n&&sa[i-1]+k<n&&y[sa[i]+k]==y[sa[i-1]+k] ? m-1 : m++; 26 } 27 if(m > n) break; 28 } 29 memcpy(rank, x, n * sizeof(int)); 30 for(i = 0, p = 0; i < n; ++i) if(rank[i]) { 31 if(p) --p; 32 k = sa[rank[i]-1]; 33 while(s[i+p] == s[k+p]) ++p; 34 height[rank[i]] = p; 35 } 36 } 37 } 38 int main() { 39 register int i, ans = 0; 40 gets(s); 41 n = strlen(s); 42 SABuilder::work(); 43 printf("%d", ans); 44 return 0; 45 }
以上是关于后缀树组(SA)初探的主要内容,如果未能解决你的问题,请参考以下文章
CF504E Misha and LCP on Tree(树链剖分+后缀树组)