BZOJ3940: [Usaco2015 Feb]Censoring (AC自动机)

题意:在文本串上删除一些字符串 每次优先删除从左边开始第一个满足的

   删除后剩下的串连在一起重复删除步骤 直到不能删

题解:建fail 用栈存当前放进了那些字符 如果可以删 fail指针跳到前面去

       好菜啊TAT 原来还有个优化

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

char t[100005];
char s[100005];
int n, cnt, tot;
int ch[100005][26];
int val[100005];
int que[100005];
int fail[100005];
char ans[100005];
int id[100005];

void insert() {
    int len = strlen(s);

    int now = 1;
    for(int i = 0; i < len; i++) {
        int c = s[i] - 'a';
        if(!ch[now][c]) ch[now][c] = ++cnt;
        now = ch[now][c];
    }
    val[now] = len;
}

void getfail() {
    int l1 = 1, r1 = 0;
    que[++r1] = 1;

    while(l1 <= r1) {
        int now = que[l1];
        l1++;

        for(int i = 0; i < 26; i++) {
            if(ch[now][i]) {
                int y = fail[now];
                while(!ch[y][i]) y = fail[y];
                fail[ch[now][i]] = ch[y][i];
                que[++r1] = ch[now][i];
            }
            else ch[now][i] = ch[fail[now]][i];
        }
    }
}

void init() {
    cnt = 1;
    tot = 0;
    id[0] = 1;
    for(int i = 0; i < 26; i++) ch[0][i] = 1;
}

int main() {
    init();
    scanf("%s", t + 1);
    int len = strlen(t + 1);

    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%s", s);
        insert();
    }
    getfail();

    int now = 1;
    for(int i = 1; i <= len; i++) {
        int c = t[i] - 'a';

        now = ch[now][c];
        id[++tot] = now;
        ans[tot] = t[i];

        if(val[now]) {
            tot -= val[now];
            now = id[tot];
        }
    }
    for(int i = 1; i <= tot; i++) printf("%c", ans[i]);
    puts("");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/lwqq3/p/10960385.html