【hdu 5880】 【AC自动机+差分法】Family View 把匹配到的敏感词改成*

来源:互联网 发布:effective java的缺点 编辑:程序博客网 时间:2024/06/06 01:14

传送门:HDU 5880 Family View

描述:

Family View

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


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
13trumprioDonald 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.
 

Source
2016 ACM/ICPC Asia Regional Qingdao Online
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5899 5897 5896 5894 5893 


题意:

给一些敏感词,然后下面的串只要出现敏感词就输出*

思路:

首先介绍下什么是差分法。比如给你一个长度为n的数组cnt,一开始全是0。现在如果让你从下标2~4的位置都+1,怎么做?cnt[2]++,cnt[5]--

数组变成了0 0 1 0 0 -1 0....,我们再进行for(int i=0;i<n;++i)cnt[i]+=cnt[i-1];  现在变成了0 0 1 1 1 0 0...是不是2~4都+1了?

总结一下,差分的想法就是在区间a~b中+1,等价于cnt[a]++,cnt[b+1]--,然后再处理一边前缀和就行了。

这题AC自动机匹配成功是用差分法搞一下匹配到的字符串就行了


拿kuangbin的hdu2222的模版改了不到十行的代码就过了,在每一个串的结尾标记一下最长的那个串的长度,然后输出的时候直接判断标记就行了

bin神的模版真心给力而且好改

代码:

#include<bits/stdc++.h>using namespace std;const int maxn=1000010;int ans[maxn],cnt[maxn];//每个点结果数值 统计长度struct Trie{  int next[maxn][26],fail[maxn],end[maxn];  int root,L,kk;  int newnode(){    for(int i = 0;i < 26;i++)      next[L][i] = -1;    end[L++] = 0;    return L-1;  }  void init(){    L = 0,kk=0;    root = newnode();    memset(ans, 0, sizeof(ans));  }  void insert(char buf[]){    int len = strlen(buf);    int now = root;    for(int i = 0;i < len;i++){      if(next[now][buf[i]-'a'] == -1)        next[now][buf[i]-'a'] = newnode();      now = next[now][buf[i]-'a'];    }    //修改    if(end[now]==0){      kk++;end[now]=kk;      cnt[kk]=len;//单独匹配串的长度    }else{      if(cnt[end[now]]<len)cnt[end[now]]=len;    }    //  }  void build(){    queue<int>Q;    fail[root] = root;    for(int i = 0;i < 26;i++)      if(next[root][i] == -1)        next[root][i] = root;      else{        fail[next[root][i]] = root;        Q.push(next[root][i]);      }    while( !Q.empty() ){      int now = Q.front();      Q.pop();      for(int i = 0;i < 26;i++)        if(next[now][i] == -1)          next[now][i] = next[fail[now]][i];        else{          fail[next[now][i]]=next[fail[now]][i];          Q.push(next[now][i]);        }    }  }  int query(char buf[]){    int len = strlen(buf);    int now = root;    int res = 0;    for(int i = 0;i < len;i++){      if(buf[i]>='a' && buf[i]<='z')now = next[now][buf[i]-'a'];      else if(buf[i]>='A' && buf[i]<='Z')now = next[now][buf[i]-'A'];      else continue;      int temp = now;      while( temp != root ){        //修改        ans[i+1]--;ans[i-cnt[end[temp]]+1]++;/*        res += end[temp];        end[temp] = 0;*/        //        temp = fail[temp];      }    }    return res;  }  void debug(){    for(int i = 0;i < L;i++){      printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);      for(int j = 0;j < 26;j++)        printf("%2d",next[i][j]);        printf("]\n");    }  }};char buf[maxn];Trie ac;int main(){  int T;  int n;  scanf("%d",&T);  while( T-- ){    scanf("%d",&n);    ac.init();    for(int i = 0;i < n;i++){      scanf("%s",buf);      ac.insert(buf);    }    ac.build();    getchar();    gets(buf);//只能用gets    ac.query(buf);    int len=strlen(buf),sum=0;    for(int i=0; i<len; i++){      sum+=ans[i];      if(sum<=0)printf("%c",buf[i]);      else printf("*");    }    puts("");  }  return 0;}



0 0