zoukankan      html  css  js  c++  java
  • 洛谷-P3796-【模板】AC自动机(加强版)

    题目传送门

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

    sol:AC自动机,在fail边的基础上再加一个last边,指向真正有效的节点,跳fail边改成跳last边来跳过无效点。

    • AC自动机
      #include <bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      typedef pair<int, int> PII;
      const int MAXN = 11000;
      struct Trie {
          int son[MAXN][26], fail[MAXN], last[MAXN];
          int cnt[MAXN], inde[MAXN]; int tot, root, _max;
          vector<int> vec; string str[160];
          int add_node() {
              memset(son[tot], -1, sizeof(son[tot]));
              cnt[tot] = 0; inde[tot] = -1;
              return tot ++;
          }
          void init() {
              tot = _max = 0;
              root = add_node();
          }
          void insert(char* s, int id) {
              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];
              }
              inde[p] = id;
              str[id] = s;
          }
          void build() {
              queue<int> que;
              fail[root] = last[root] = root;
              for (int i = 0; i < 26; i++) {
                  if (son[root][i] == -1) son[root][i] = root;
                  else {
                      fail[son[root][i]] = root;
                      last[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];
                          if (inde[son[fail[p]][i]] != -1)
                              last[son[p][i]] = son[fail[p]][i];
                          else
                              last[son[p][i]] = son[last[p]][i];
                          que.push(son[p][i]);
                      }
                  }
              }
          }
          void slove(char* s) {
              int p = root;
              for (int i = 0; s[i]; i++) {
                  int index = s[i] - 'a';
                  p = son[p][index];
                  for (int tmp = p; tmp != root; tmp = last[tmp]) {
                      if (inde[tmp] == -1) continue;
                      cnt[tmp] ++;
                      if (cnt[tmp] > _max) {
                          _max = cnt[tmp];
                          vec.clear();
                          vec.push_back(inde[tmp]);
                      } else if (cnt[tmp] == _max) {
                          vec.push_back(inde[tmp]);
                      }
                  }
              }
          }
          void output() {
              printf("%d
      ", _max);
              sort(vec.begin(), vec.end());
              for (int i = 0; i < vec.size(); i++)
                  cout << str[vec[i]] << endl;
          }
      } ac;
      char s[1000010];
      int main() {
          int n;
          while (scanf("%d", &n) && n) {
              ac.init();
              for (int i = 1; i <= n; i++) {
                  scanf("%s", s);
                  ac.insert(s, i);
              }
              ac.build(); scanf("%s", s);
              ac.slove(s); ac.output();
          }
          return 0;
      }
  • 相关阅读:
    shell
    regionMatches方法
    ==
    使用INTO子句创建新表
    数据库除运算
    数据库笛卡尔积运算
    人生格言
    刚开通~
    Nginx:413 Request Entity Too Large
    ORACLE 查看并修改最大连接数
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/12233315.html
Copyright © 2011-2022 走看看