首页 > 编程语言 > 详细

POJ 3415 后缀数组

时间:2017-09-12 23:49:24      阅读:268      评论:0      收藏:0      [点我收藏+]

链接:

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 后缀数组

原文:http://www.cnblogs.com/baocong/p/7512813.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!