POJ 3415 后缀数组
Posted Flowersea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3415 后缀数组相关的知识,希望对你有一定的参考价值。
链接:
http://poj.org/problem?id=3415
题意:
统计A和B长度不小于K的公共子串个数。
题解:
将A和B拼接后,利用单调栈累计分属两者的后缀对应的LCP-K+1即为答案
代码:
31 int n, k; 32 int Rank[MAXN], tmp[MAXN]; 33 int sa[MAXN], lcp[MAXN]; 34 35 bool compare_sa(int i, int j) { 36 if (Rank[i] != Rank[j]) return Rank[i] < Rank[j]; 37 else { 38 int ri = i + k <= n ? Rank[i + k] : -1; 39 int rj = j + k <= n ? Rank[j + k] : -1; 40 return ri < rj; 41 } 42 } 43 44 void construct_sa(string S, int *sa) { 45 n = S.length(); 46 for (int i = 0; i <= n; i++) { 47 sa[i] = i; 48 Rank[i] = i < n ? S[i] : -1; 49 } 50 for (k = 1; k <= n; k *= 2) { 51 sort(sa, sa + n + 1, compare_sa); 52 tmp[sa[0]] = 0; 53 for (int i = 1; i <= n; i++) 54 tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0); 55 for (int i = 0; i <= n; i++) Rank[i] = tmp[i]; 56 } 57 } 58 59 void construct_lcp(string S, int *sa, int *lcp) { 60 int n = S.length(); 61 for (int i = 0; i <= n; i++) Rank[sa[i]] = i; 62 int h = 0; 63 lcp[0] = 0; 64 for (int i = 0; i < n; i++) { 65 int j = sa[Rank[i] - 1]; 66 if (h > 0) h--; 67 for (; j + h < n && i + h < n; h++) 68 if (S[j + h] != S[i + h]) break; 69 lcp[Rank[i] - 1] = h; 70 } 71 } 72 73 int st[MAXN][2]; 74 ll contribution, top; 75 using namespace std; 76 77 ll solve(int k, int n1, bool is_s1) { 78 ll ans = 0; 79 rep(i, 0, n) { 80 if (lcp[i] < k) { 81 top = contribution = 0; 82 continue; 83 } 84 int size = 0; 85 if (is_s1 && sa[i] < n1 || !is_s1 && sa[i] > n1) { 86 ++size; 87 contribution += lcp[i] - k + 1; 88 } 89 while (top > 0 && lcp[i] <= st[top - 1][0]) { 90 --top; 91 contribution -= st[top][1] * (st[top][0] - lcp[i]); 92 size += st[top][1]; 93 } 94 if (size) { 95 st[top][0] = lcp[i]; 96 st[top][1] = size; 97 ++top; 98 } 99 if (is_s1 && sa[i + 1] > n1 || !is_s1 && sa[i + 1] < n1) ans += contribution; 100 } 101 return ans; 102 } 103 104 int main() { 105 ios::sync_with_stdio(false), cin.tie(0); 106 int k; 107 while (cin >> k, k) { 108 string a, b; 109 cin >> a >> b; 110 int n1 = a.length(); 111 string s = a + ‘$‘ + b; 112 construct_sa(s, sa); 113 construct_lcp(s, sa, lcp); 114 cout << solve(k, n1, true) + solve(k, n1, false) << endl; 115 } 116 return 0; 117 }
以上是关于POJ 3415 后缀数组的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3415 Common Substrings ——后缀数组
POJ3415 Common Substrings 后缀数组 + 单调栈