1. 程式人生 > >[Luogu P3121] [BZOJ 3940] [USACO15FEB]審查(黃金)Censoring (Gold)

[Luogu P3121] [BZOJ 3940] [USACO15FEB]審查(黃金)Censoring (Gold)

洛谷傳送門

BZOJ傳送門

題目描述

FJ把雜誌上所有的文章摘抄了下來並把它變成了一個長度不超過 1 0 5 10^5 的字串 S

S 。他有一個包含 n n 個單詞的列表,列表裡的 n n 個單詞記為 t
1 . . . t N t_1...t_N
。他希望從 S
S
中刪除這些單詞。

FJ每次在 S S 中找到最早出現的列表中的單詞(最早出現指該單詞的開始位置最小),然後從 S S 中刪除這個單詞。他重複這個操作直到 S S 中沒有列表裡的單詞為止。注意刪除一個單詞後可能會導致 S S 中出現另一個列表中的單詞

FJ注意到列表中的單詞不會出現一個單詞是另一個單詞子串的情況,這意味著每個列表中的單詞在 S S 中出現的開始位置是互不相同的

請幫助FJ完成這些操作並輸出最後的 S S

輸入輸出格式

輸入格式:

第一行一個字串 S S

第二行一個正整數 n n

以下 n n 行, 每行一個字串, 表示 t 1 . . . t N t_1...t_N , 長度總和不超過 1 0 5 10^5

輸出格式:

一行一個字串, 表示刪除操作完成後的 S S

輸入輸出樣例

輸入樣例#1:

begintheescapexecutionatthebreakofdawn 
2 
escape 
execution 

輸出樣例#1:

beginthatthebreakofdawn 

解題分析

對模板串建立 A C AC 自動機, 然後把匹配串跑一遍,用棧記錄位置即可。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cctype>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 100500
int fail[MX], l[MX], pos[MX];
int son[MX][26];
char mod[MX], dat[MX], sta[MX];
int n, root, ct, top;
std::queue <int> q;
IN void insert(char *str)
{
    int len = std::strlen(str);
    R int now = root, id;
    for (R int i = 0; i < len; ++i)
    {
        id = str[i] - 'a';
        if (!son[now][id]) son[now][id] = ++ct;
        now = son[now][id];
    }
    l[now] = len;
}
IN void build()
{
    R int now;
    for (R int i = 0; i < 26; ++i) if (son[root][i]) q.push(son[root][i]);
    W (!q.empty())
    {
        now = q.front(); q.pop();
        for (R int i = 0; i < 26; ++i) if (son[now][i]) fail[son[now][i]] = son[fail[now]][i], q.push(son[now][i]);
        else son[now][i] = son[fail[now]][i];
    }
}
IN void solve(char *str)
{
    int len = std::strlen(str);
    R int now = root, id;
    for (R int i = 0; i < len; ++i)
    {
        id = str[i] - 'a';
        now = son[now][id];
        sta[++top] = str[i], pos[top] = now;
        W (l[now])
        {
            top -= l[now];
            now = pos[top];
        }
    }
    for (R int i = 1; i <= top; ++i) printf("%c", sta[i]); puts("");
}
int main(void)
{
    scanf("%s%d", dat, &n);
    for (R int i = 1; i <= n; ++i)
    {
        scanf("%s", mod);
        insert(mod);
    }
    build();
    solve(dat);
}