• 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 PII st[MAXN];
     74 ll contribution, top;
     75 
     76 ll solve(int k, int n1, bool is_s1) {
     77     ll ans = 0;
     78     rep(i, 0, n) {
     79         if (lcp[i] < k) {
     80             top = contribution = 0;
     81             continue;
     82         }
     83         int size = 0;
     84         if (is_s1 && sa[i] < n1 || !is_s1 && sa[i] > n1) {
     85             size++;
     86             contribution += lcp[i] - k + 1;
     87         }
     88         while (top > 0 && st[top].first >= lcp[i]) {
     89             contribution -= st[top].second*(st[top].first - lcp[i]);
     90             size += st[top].second;
     91             top--;
     92         }
     93         st[++top] = mp(lcp[i], size);
     94         if (is_s1 && sa[i + 1] > n1 || !is_s1 && sa[i + 1] < n1) ans += contribution;
     95     }
     96     return ans;
     97 }
     98 
     99 int main() {
    100     ios::sync_with_stdio(false), cin.tie(0);
    101     int k;
    102     while (cin >> k, k) {
    103         string a, b;
    104         cin >> a >> b;
    105         int n1 = a.length();
    106         string s = a + '$' + b;
    107         construct_sa(s, sa);
    108         construct_lcp(s, sa, lcp);
    109         cout << solve(k, n1, true) + solve(k, n1, false) << endl;
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    cmd常用命令
    快捷键
    leetcode:Sort List(一个链表的归并排序)
    leetcode:Merge Two Sorted Lists(有序链表的归并)
    leetcode:Search for a Range(数组,二分查找)
    leetcode:Search a 2D Matrix(数组,二分查找)
    实时操作系统与分时操作系统
    第四章函数作业题,函数模板
    第四章函数作业题,函数的重载
    第四章函数作业题,内置函数
  • 原文地址:https://www.cnblogs.com/baocong/p/7512813.html
Copyright © 2020-2023  润新知