P3808 【模板】AC自动机(简单版)

P3808 【模板】AC自动机(简单版)

https://www.luogu.org/problemnew/show/P3808

 
分析:

  建立AC自动机,然后在文本串扫一遍,统计每个串出现的次数。

 

代码:

换了种写法

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 500100;
char str[N << 1], s[110];
int ch[N][26], fail[N], val[N], last[N], q[N], L, R, Index;

void Insert(char *s) {
    int len = strlen(s), u = 0;
    for (int i=0; i<len; ++i) {
        int c = s[i] - 'a';
        if (!ch[u][c]) ch[u][c] = ++Index;
        u = ch[u][c];
    }
    val[u] ++;
}
void build() {
    L = 1;R = 0;
    fail[0] = 0;
    for (int c=0; c<26; ++c) {
        int u = ch[0][c];
        if (u) fail[u] = 0, q[++R] = u, last[u] = 0;
    }
    while (L <= R) {
        int u = q[L++];
        for (int c=0; c<26; ++c) {
            int v = ch[u][c];
            if (!v) ch[u][c] = ch[fail[u]][c];
            else {
                q[++R] = v;
                fail[v] = ch[fail[u]][c];
                last[v] = val[fail[v]] ? fail[v] : last[fail[v]];
            }
        }
    }
}

int find(char *s) {
    int Ans = 0, u = 0, len = strlen(s);
    for (int i=0; i<len; ++i) {
        int c = s[i] - 'a';
        u = ch[u][c];
        if (val[u]) Ans += val[u], val[u] = 0;
        int p = u;
        while (last[p]) {
            p = last[p];
            if (val[p]) Ans += val[p], val[p] = 0;
        }
    }
    return Ans;
}

int main () {
    int n;
    scanf("%d", &n);
    while (n--) {
        scanf("%s", s);
        Insert(s);
    }
    build();
    scanf("%s",str);
    printf("%d\n",find(str));
    return 0;
}
View Code

 

 
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 500100;
char str[N << 1], s[110];
int ch[N][26], fail[N], val[N], last[N], q[N], L, R, Index;

void Insert(char *s) {
    int len = strlen(s), u = 0;
    for (int i=0; i<len; ++i) {
        int c = s[i] - 'a';
        if (!ch[u][c]) ch[u][c] = ++Index;
        u = ch[u][c];
    }
    val[u] ++;
}
void build() {
    L = 1;R = 0;
    fail[0] = 0;
    for (int c=0; c<26; ++c) {
        int u = ch[0][c];
        if (u) fail[u] = 0, q[++R] = u, last[u] = 0;
    }
    while (L <= R) {
        int u = q[L++];
        for (int c=0; c<26; ++c) {
            int v = ch[u][c];
            if (!v) {
                ch[u][c] = ch[fail[u]][c];
                continue;
            }
            q[++R] = v;
            int p = fail[u];
            while (p && !ch[p][c]) p = fail[p];
            fail[v] = ch[p][c];
            last[v] = val[fail[v]] ? fail[v] : last[fail[v]];
        }
    }
}

int find(char *s) {
    int Ans = 0, u = 0, len = strlen(s);
    for (int i=0; i<len; ++i) {
        int c = s[i] - 'a';
        u = ch[u][c];
        if (val[u]) Ans += val[u], val[u] = 0;
        int p = u;
        while (last[p]) {
            p = last[p];
            if (val[p]) Ans += val[p], val[p] = 0;
        }
    }
    return Ans;
}

int main () {
    int n;
    scanf("%d", &n);
    while (n--) {
        scanf("%s", s);
        Insert(s);
    }
    build();
    scanf("%s",str);
    printf("%d\n",find(str));
    return 0;
}
View Code

 

posted @ 2018-07-23 17:54  MJT12044  阅读(246)  评论(0编辑  收藏  举报