[洛谷P3808]【模板】AC自动机(简单版)

题目大意:给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

题解:AC自动机

卡点:

C++ Code:

#include <cstdio>
#include <queue>
#include <cstring>
#define maxn 1000010
using namespace std;
int n;
char s[maxn];
int nxt[maxn][26], fail[maxn], cnt[maxn], tot;
int root = 0;
queue<int> q;
void add(char *s) {
    int now = root, len = strlen(s);
    for (int i = 0; i < len; i++) {
        if (nxt[now][s[i] - 'a']) now = nxt[now][s[i] - 'a'];
        else now = nxt[now][s[i] - 'a'] = ++tot;
    }
    cnt[now]++;
}
void build() {
    for (int i = 0; i < 26; i++) 
        if (nxt[root][i]) fail[nxt[root][i]] = root, q.push(nxt[root][i]);
    while (!q.empty()) {
        int x = q.front(); q.pop();
        for (int i = 0; i < 26; i++) {
            if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]);
            else nxt[x][i] = nxt[fail[x]][i];
        }
    }
}
int ask(char *s) {
    int now = root, ans = 0, len = strlen(s);
    for (int i = 0; i < len; i++) {
        now = nxt[now][s[i] - 'a'];
        for (int j = now; j && ~cnt[j]; j = fail[j]) ans += cnt[j], cnt[j] = -1;
    }
    return ans;
} 
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%s", s);
        add(s);
    }
    build();
    scanf("%s", s);
    printf("%d\n", ask(s));
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Memory-of-winter/p/9379427.html