AC自动机模板

大致步骤:

一:Trie插入 {

 遍历字符串,有节点就进入节点,没有节点就创建节点后进入节点。 

}

二:构建fail指针 {

  fail指向当前Trie中含有的最长后缀字符串。

  BFS遍历每一层

  动归思想:{

     对当前这一层的某个节点x,找到其父节点的fail所指的节点y (这样可以保证x前面一段的最长前缀,也就是之前的状态),如果当前节点y下有x,那么x的fail指向y,否则一直跳fail直到root。

  }

}

三:查询 {

  遍历字符串,能匹配则继续,不然一直跳fail直到root

}

模板:总共n个t串,求s串中包含的t串的数目。

#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <queue>
#include <deque>
#include <list>
#include <climits>
#include <bitset>
#include <fstream>
#include <algorithm>
#include <functional>
#include <stack>
#include <string>
#include <cmath>
#define fi first
#define se second
#define re register
#define ls i << 1
#define rs i << 1 | 1
#define pb push_back
#define pii pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define mod 10007

//#define int long long

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const int inf = 0x3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
int tt;
inline int rd(){
  int x = 0, f = 1; char ch = getchar();
  while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
  while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
  return x * f;
}

void out(int a) {
  if (a < 0) putchar('-'), a = -a;
  if (a >= 10) out(a / 10);
  putchar(a % 10 + '0');
}
queue<int> q;
const int N = 1e6+10;
char s[N], t[55];
int idx, ans;
struct Trie{
  int son[26];
  int fail = -1, cnt = 0;
  int flag = 0;
};
vector<Trie> node;

void ins(char* s) {
  int p = 0, len = strlen(s);
  for (int i = 0; i < len; i++) {
    int now = s[i] - 'a';
    if (!node[p].son[now]) node[p].son[now] = ++idx;
    p = node[p].son[now];
  }
  node[p].cnt++;
}

void getfail() {
  while (!q.empty()) q.pop();
  for (int i = 0; i < 26; i++) {
    if (node[0].son[i]) {
      int son = node[0].son[i];
      node[son].fail = 0;
      q.push(son);
    }
  }
  while (!q.empty()) {
    int f = q.front();
    q.pop();
    for (int i = 0; i < 26; i++) {
      if (node[f].son[i]) {
        int now = node[f].son[i];
        int fafail = node[f].fail;
        while (~fafail && !node[fafail].son[i]) fafail = node[fafail].fail;
        if (~fafail) node[now].fail = node[fafail].son[i];
        else node[now].fail = 0;
        q.push(now);
      }
    }
  }
}

void query(char* t) {
  int p = 0, len = strlen(t);
  for (int i = 0; i < len; i++) {
    int word = t[i] - 'a';
    while (!node[p].son[word] && ~node[p].fail) p = node[p].fail;
    if (node[p].son[word]) p = node[p].son[word];
    else continue;
    int p2 = p;
    while (~node[p2].fail) {
      if (node[p2].flag) break;
      node[p2].flag = 1;
      ans += node[p2].cnt;
      p2 = node[p2].fail;
    }
  }
}

void solve() {
  node.clear();
  node.resize(1000005);
  idx = ans = 0;
  int n = rd();
  for (int i = 1; i <= n; i++)
  scanf("%s",t),ins(t);
  getfail();
  scanf("%s",s);
  query(s);
  printf("%d\n",ans);
}

signed main(){
  for (int tt = rd(); tt--;)
  solve();
  return 0;
}

 

posted @ 2020-08-30 00:14  Kimyon  阅读(161)  评论(0编辑  收藏  举报