• Longest Common Substring II SPOJ


    题意:多个串的最大公共子串
    思路:用广义后缀数组构造后,记录每个点包含的节点,最后判断那个点包含所有点。

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN 2000000  // 双倍字符串长度
    #define CHAR_NUM 30   // 字符集个数,注意修改下方的 (-'a')
    #define NUM 15        // 字符串个数
    struct exSAM {
      int len[MAXN];             // 节点长度
      int link[MAXN];            // 后缀链接,link
      int next[MAXN][CHAR_NUM];  // 转移
      int tot;                   // 节点总数:[0, tot)
      int lenSorted[MAXN];   // 按照 len 排序后的数组,仅排序 [1, tot)
                             // 部分,最终下标范围 [0, tot - 1)
      int sizeC[MAXN][NUM];  // 表示某个字符串的子串个数
      int curString;         // 字符串实际个数
      /**
       * 计数排序使用的辅助空间数组
       */
      int lc[MAXN];  // 统计个数
      void init() {
        tot = 1;
        link[0] = -1;
      }
      int insertSAM(int last, int c) {
        int cur = next[last][c];
        len[cur] = len[last] + 1;
        int p = link[last];
        while (p != -1) {
          if (!next[p][c])
            next[p][c] = cur;
          else
            break;
          p = link[p];
        }
        if (p == -1) {
          link[cur] = 0;
          return cur;
        }
        int q = next[p][c];
        if (len[p] + 1 == len[q]) {
          link[cur] = q;
          return cur;
        }
        int clone = tot++;
        for (int i = 0; i < CHAR_NUM; ++i)
          next[clone][i] = len[next[q][i]] != 0 ? next[q][i] : 0;
        len[clone] = len[p] + 1;
        while (p != -1 && next[p][c] == q) {
          next[p][c] = clone;
          p = link[p];
        }
        link[clone] = link[q];
        link[cur] = clone;
        link[q] = clone;
        return cur;
      }
      int insertTrie(int cur, int c) {
        if (!next[cur][c]) next[cur][c] = tot++;
        sizeC[next[cur][c]][curString]++;
        return next[cur][c];
      }
      void insert(const string &s) {
        int root = 0;
        for (auto ch : s) root = insertTrie(root, ch - 'a');
        curString++;
      }
      void insert(const char *s, int n) {
        int root = 0;
        for (int i = 0; i < n; ++i) root = insertTrie(root, s[i] - 'a');
        curString++;
      }
      void build() {
        queue<pair<int, int>> q;
        for (int i = 0; i < 26; ++i)
          if (next[0][i]) q.push({i, 0});
        while (!q.empty()) {
          auto item = q.front();
          q.pop();
          auto last = insertSAM(item.second, item.first);
          for (int i = 0; i < 26; ++i)
            if (next[last][i]) q.push({i, last});
        }
      }
      void sortLen() {
        for (int i = 1; i < tot; ++i) lc[i] = 0;
        for (int i = 1; i < tot; ++i) lc[len[i]]++;
        for (int i = 2; i < tot; ++i) lc[i] += lc[i - 1];
        for (int i = 1; i < tot; ++i) lenSorted[--lc[len[i]]] = i;
      }
      void getSizeLen() {
        for (int i = tot - 2; i >= 0; --i)
          for (int j = 0; j < curString; ++j)
            sizeC[link[lenSorted[i]]][j] += sizeC[lenSorted[i]][j];
      }
      void debug() {
        cout << "     i      len      link       ";
        for (int i = 0; i < 26; ++i) cout << "  " << (char)('a' + i);
        cout << endl;
        for (int i = 0; i < tot; ++i) {
          cout << "i: " << setw(3) << i << " len: " << setw(3) << len[i]
               << " link: " << setw(3) << link[i] << " Next: ";
          for (int j = 0; j < CHAR_NUM; ++j) {
            cout << setw(3) << next[i][j];
          }
          cout << endl;
        }
      }
    } exSam;
    int main() {
      exSam.init();
      string s;
      while (cin >> s) exSam.insert(s);
      exSam.build();
      exSam.sortLen();
      exSam.getSizeLen();
      int ans = 0;
      for (int i = 0; i < exSam.tot; ++i) {
        bool flag = true;
        for (int j = 0; j < exSam.curString; ++j) {
          if (!exSam.sizeC[i][j]) {
            flag = false;
            break;
          }
        }
        if (flag) ans = max(ans, exSam.len[i]);
      }
      cout << ans << endl;
    }
    
  • 相关阅读:
    [BZOJ2287]【POJ Challenge】消失之物(DP)
    [BZOJ1596] [Usaco2008 Jan]电话网络(树形DP || 贪心)
    [BZOJ3339] Rmq Problem(线段树)
    [BZOJ3378] [Usaco2004 Open]MooFest 狂欢节(树状数组)
    [BZOJ1595] [Usaco2008 Jan]人工湖(单调栈)
    [BZOJ1594] [Usaco2008 Jan]猜数游戏(二分 + 并查集)
    [POJ2778]DNA Sequence(AC自动机 + DP + 矩阵优化)
    [TyvjP1519] 博彩游戏(AC自动机 + DP)
    【模板】AC自动机
    [poj3744] Scout YYF I【概率dp 数学期望】
  • 原文地址:https://www.cnblogs.com/2462478392Lee/p/13813519.html
Copyright © 2020-2023  润新知