zoukankan      html  css  js  c++  java
  • [Codeforces547E]Mike and Friends

    给定 (n) 个字符串 (S_1, S_2, dots, S_n),有 (q) 次询问,每次询问 (S_k)(S_l, S_{l + 1}, dots, S_r) 中的出现次数。

    (n, sum|S| leq 2 imes 10^5, q leq 5 imes 10^5)

    (n) 个串建 AC 自动机(广义后缀自动机也可以),(S_k)(S_l) 中出现,即 (S_l) 的某个前缀在 fail 树上不断向上跳能到达 (S_k) 所在的状态。

    所以转换成 fail 树上的问题,将询问离线,拆成两个前缀和之差。

    每次单点加一 (S_i) 的所有前缀表示的状态,区间查询 (S_k) 子树和即可。

    #include <bits/stdc++.h>
    
    template <class T, class U>
    inline bool smin(T &x, const U &y) { return y < x ? x = y, 1 : 0; }
    template <class T, class U>
    inline bool smax(T &x, const U &y) { return x < y ? x = y, 1 : 0; }
    typedef long long LL;
    typedef std::pair<int, int> PII;
    
    constexpr int N(2e5 + 5);
    
    int n, m, cnt, ch[N][26], fa[N], pos[N];
    std::vector<int> g[N];
    int ins(const std::string &s) {
      int o = 0;
      for (char c : s) {
        if (!ch[o][c - 'a']) ch[o][c - 'a'] = ++cnt;
        o = ch[o][c - 'a']; 
      }
      return o;
    }
    int in[N], out[N];
    void dfs(int x) {
      static int c = 0;
      in[x] = ++c;
      for (int y : g[x]) dfs(y);
      out[x] = c;
    }
    void build() {
      static int q[N], l, r;
      q[l = r = 1] = 0;
      while (l <= r) {
        int o = q[l++];
        if (fa[o] == o) fa[o] = 0;
        for (int i = 0; i < 26; i++) {
          (ch[o][i] ? fa[q[++r] = ch[o][i]] : ch[o][i]) = ch[fa[o]][i];
        }
      }
      for (int i = 1; i <= cnt; i++) g[fa[i]].push_back(i);
      dfs(0);
    }
    // FenwickTree
    int c[N];
    inline void add(int p, int x) {
      for (; p <= cnt + 1; p += p & -p) c[p] += x;
    }
    inline int ask(int p) {
      int r = 0;
      for (; p; p -= p & -p) r += c[p];
      return r;
    }
    
    std::string s[N];
    struct Query {
      int k, r, id, tp;
    } q[N * 5];
    int ans[N * 3];
    int main() {
      std::ios::sync_with_stdio(false);
      std::cin.tie(nullptr);
      std::cin >> n >> m;
      for (int i = 1; i <= n; i++) {
        std::cin >> s[i];
        pos[i] = ins(s[i]);
      }
      build();
      for (int i = 1, k, l, r; i <= m; i++) {
        std::cin >> l >> r >> k;
        q[i] = { k, l - 1, i, -1 };
        q[i + m] = { k, r, i, 1 };
      }
      std::sort(q + 1, q + 1 + m + m, [](const Query &a, const Query &b) { return a.r < b.r; });
      for (int i = 1, t = 1; i <= m << 1; i++) {
        while (t <= q[i].r) {
          int o = 0;
          for (char c : s[t]) {
            o = ch[o][c - 'a'];
            assert(in[o]);
            add(in[o], 1);
          }
          t++;
        }
        int k = pos[q[i].k];
        ans[q[i].id] += q[i].tp * (ask(out[k]) - ask(in[k] - 1));
      }
      for (int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
      return 0;
    }
    
  • 相关阅读:
    The Sixth Assignment
    The fifth assigiment
    网络编程
    面向对象
    python数据类型之集合
    python数据类型之列表
    python数据类型之字符串
    python数据类型之字典
    python数据类型之元组
    常用模块
  • 原文地址:https://www.cnblogs.com/HolyK/p/14162367.html
Copyright © 2011-2022 走看看