首页 > 代码库 > 后缀树组(SA)初探
后缀树组(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)初探
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。