Family View

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1253    Accepted Submission(s): 248


Problem Description
Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and social networking services. A family view can help you to prevent your children access to some content which are not suitable for them.

Take an MMORPG game as an example, given a sentence T, and a list of forbidden words {P}, your job is to use '*' to subsititute all the characters, which is a part of the substring matched with at least one forbidden word in the list (case-insensitive).

For example, T is: "I love Beijing's Tiananmen, the sun rises over Tiananmen. Our great leader Chairman Mao, he leades us marching on."

And {P} is: {"tiananmen", "eat"}

The result should be: "I love Beijing's *********, the sun rises over *********. Our gr*** leader Chairman Mao, he leades us marching on."
 

Input
The first line contains the number of test cases. For each test case:
The first line contains an integer n, represneting the size of the forbidden words list P. Each line of the next n lines contains a forbidden words Pi (1|Pi|1000000,|Pi|1000000) where Pi only contains lowercase letters.

The last line contains a string T (|T|1000000).
 

Output
For each case output the sentence in a line.
 

Sample Input
1 3 trump ri o Donald John Trump (born June 14, 1946) is an American businessman, television personality, author, politician, and the Republican Party nominee for President of the United States in the 2016 election. He is chairman of The Trump Organization, which is the principal holding company for his real estate ventures and other business interests.
 

Sample Output
D*nald J*hn ***** (b*rn June 14, 1946) is an Ame**can businessman, televisi*n pers*nality, auth*r, p*litician, and the Republican Party n*minee f*r President *f the United States in the 2016 electi*n. He is chairman *f The ***** *rganizati*n, which is the p**ncipal h*lding c*mpany f*r his real estate ventures and *ther business interests.
 

【题意】给出了一些敏感词,现在要把文本里面的敏感词全部替换成*号,问替换之后的字符串是什么?
【解题方法】其实大概也就是AC自动机的模板题。但是这题不注意就会陷入ML的结局。为什么?首先我们这题我们一定不能用memset一次性的清空内存,这样内存肯定炸的,那么来说一下,这道题怎么去把模式串改变成*号吧!容易想到我们需要对模式串建立ac自动机,然后在ac自动机上跑文本。最关键是如何标记文本里面的敏感词,这里我们需要用到一个区间[L,R]标记的小技巧!把左端点的标记-1,右端点的标记+1,那么打完标记之后,扫一遍就知道哪些该替换为敏感词了!
【AC 代码】
//
//Created by just_sort 2016/9/23 14:43
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxnode = 1000005;
const int max_size = 26;
struct AcAutomata
{
    int sz,ch[maxnode][max_size],len[maxnode],fail[maxnode],last[maxnode],cnt[maxnode];//len记录以某个节点结束的单词长度,cnt来标记敏感串位置
    bool val[maxnode];//标记单词节点
    void init(){
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
        memset(val,false,sizeof(val));
    }
    void insert(char *s){
        int u = 0;
        for(int i=0; s[i]; i++){
            int v = s[i]-'a';
            if(!ch[u][v]){
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[u][v]=sz++;
            }
            u = ch[u][v];
        }
        val[u] = true;
        len[u] = strlen(s);
    }
    void build()
    {
        queue<int>q;
        fail[0]=0;
        for(int i = 0; i < max_size; i++){
            int u = ch[0][i];
            if(u){
                fail[u] = 0;q.push(u);last[u] = 0;
            }
        }
        while(!q.empty()){
            int r = q.front();q.pop();
            for(int c = 0; c < max_size; c++){
                int u = ch[r][c];
                if(!u){
                    ch[r][c] = ch[fail[r]][c];
                    continue;
                }
                q.push(u);
                int v = fail[r];
                while(v && !ch[v][c]) v = fail[v];
                fail[u] = ch[v][c];
                last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
            }
        }
    }
    void count(int pos,int id)
    {
        if(pos){
            ++cnt[id+1];
            --cnt[id-len[pos]+1];
            count(last[pos],id);
        }
    }
    void find(char *s){
        int u = 0;
        for(int i = 0; s[i]; i++){
            if(!isalpha(s[i])) continue;
            int v = tolower(s[i]) - 'a';
            u = ch[u][v];
            if(val[u]) count(u,i);
            else if(last[u]) count(last[u],i);
        }
    }
}ac;
char ss[maxnode];
int main()
{
    int T,n;
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        ac.init();
        for(int i = 0; i < n; i++){
            scanf("%s", ss);
            ac.insert(ss);
        }
        ac.build();
        getchar();
        fgets(ss,maxnode,stdin);
        ac.find(ss);
        int ans = 0;
        for(int i = 0; ss[i]; i++){
            ans += ac.cnt[i];
            if(ans < 0) putchar('*');
            else putchar(ss[i]);
        }
    }
    return 0;
}