zoukankan      html  css  js  c++  java
  • 洛谷-P3808-【模板】AC自动机(简单版)

    题目传送门

    -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题

    sol:标准AC自动机,注意不能重复跳fail边,像"aaaaaaa...aaaaaaaa"这样的数据每跳一次fail边只往上走了一层。

    • AC自动机
      #include <bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      typedef pair<int, int> PII;
      const int MAXN = 1e6 + 10;
      struct Trie {
          int son[MAXN][26], cnt[MAXN], fail[MAXN];
          int tot, root;
          int add_node() {
              int i = tot ++;
              memset(son[i], -1, sizeof(son[i]));
              cnt[i] = 0;
              return i;
          }
          void init() {
              tot = 0;
              root = add_node();
          }
          void insert(char* s) {
              int p = root;
              for (int i = 0; s[i]; i++) {
                  int index = s[i] - 'a';
                  if (son[p][index] == -1)
                      son[p][index] = add_node();
                  p = son[p][index];
              }
              cnt[p] ++;
          }
          void build() {
              queue<int> que; fail[root] = root;
              for (int i = 0; i < 26; i++) {
                  if (son[root][i] == -1) son[root][i] = root;
                  else {
                      fail[son[root][i]] = root;
                      que.push(son[root][i]);
                  }
              }
              while (!que.empty()) {
                  int p = que.front(); que.pop();
                  for (int i = 0; i < 26; i++) {
                      if (son[p][i] == -1) son[p][i] = son[fail[p]][i];
                      else {
                          fail[son[p][i]] = son[fail[p]][i];
                          que.push(son[p][i]);
                      }
                  }
              }
          }
          int slove(char* s) {
              int p = root, res = 0;
              for (int i = 0; s[i]; i++) {
                  int index = s[i] - 'a';
                  p = son[p][index];
                  for (int tmp = p; tmp != root && cnt[tmp] != -1; tmp = fail[tmp]) {
                      res += cnt[tmp];
                      // 访问过就把cnt设置成-1,防止下次跳fail边重复进入
                      cnt[tmp] = -1;
                  }
              }
              return res;
          }
      } ac;
      char s[MAXN];
      int main() {
          ac.init();
          int n; scanf("%d", &n);
          for (int i = 1; i <= n; i++) {
              scanf("%s", s);
              ac.insert(s);
          }
          scanf("%s", s); ac.build();
          printf("%d
      ", ac.slove(s));
          return 0;
      }
  • 相关阅读:
    java实现第三届蓝桥杯拼音字母
    java实现第三届蓝桥杯数据压缩
    java实现第三届蓝桥杯数据压缩
    java实现第三届蓝桥杯数据压缩
    java实现第三届蓝桥杯数据压缩
    java实现第三届蓝桥杯数据压缩
    Jackson工具类(各种转换)
    Jackson转换JSON例子
    Jackson的用法实例分析
    SpringMVC 封装返回结果对象
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/12233309.html
Copyright © 2011-2022 走看看