Trie图/AC自动机

下面是P3808 【模板】AC自动机(简单版) 的两种写法

Trie图

const int MAXN = 1000010;
int t[MAXN][26], word[MAXN], fail[MAXN], cnt, q[MAXN];
inline void insert(char *s) {
  int u = 0;
  for (int i = 1; s[i]; ++i) {
    int v = s[i] - 'a';
    int &x = t[u][v];
    u = x ? x : x = ++cnt;
  }
  word[u]++;
}
inline void build() {
  queue<int>q;
  for (int i = 0; i < 26; ++i) if (t[0][i]) q.push(t[0][i]);
  while (!q.empty()) {
    int u = q.front(); q.pop();
    for (int i = 0; i < 26; ++i) {
      int &x = t[u][i];
      if (x) fail[x] = t[fail[u]][i], q.push(x);
      else x = t[fail[u]][i];
    }
  }
}
inline int query(char *s) {
  int u = 0, ans = 0;
  for (int j = 1; s[j]; ++j) {
    int v = s[j] - 'a';
    u = t[u][v];
    for (int i = u; i && word[i]; i = fail[i]) ans += word[i], word[i] = 0;
  }
  return ans;
}
int n; char s[1000007];
int main(void) {
  in, n;
  for (int i = 1; i <= n; ++i) {in, s + 1;insert(s);}
  build();
  in, s + 1;
  int anss = query(s);
  cout << anss;
  return 0;
}

AC自动机

int t[N][26], word[N], fail[N], cnt, n, ans;
char s[N];
void insert(char *s) {
  int u = 0;
  for (int i = 1; s[i]; ++i) {
    int &x = t[u][s[i] - 'a'];
    u = x ? x : x = ++cnt;
  }
  ++word[u];
}
void build() {
  queue<int> q;
  for (int i = 0; i < 26; ++i) if (t[0][i]) q.push(t[0][i]);
  while (!q.empty()) {
    int u = q.front(); q.pop();
    for (int i = 0; i < 26; ++i) {
      int v = t[u][i], p = fail[u];
      if (!v) continue;
      while (p && !t[p][i]) p = fail[p];
      fail[v] = t[p][i];
      q.push(v);
    } 
  }
}

void query(char *s) {
  int u = 0, p = 0;
  for (int i = 1; s[i]; ++i) {
    u = t[u][s[i] - 'a'];
    while (p && !t[p][s[i] - 'a']) p = fail[p];
    p = t[p][s[i] - 'a'];
    for (int k = p; k && word[k]; k = fail[k]) ans += word[k], word[k] = 0;
  }
}

void init() {

}

void solve() {
  n = in;
  lo1(i, n) {
    in, s + 1;
    insert(s);
  }
  build();
  in, s + 1;
  query(s);
  out, ans;
}
posted @ 2019-03-19 11:46  QvvQ  阅读(135)  评论(0编辑  收藏  举报