http://acm.split.hdu.edu.cn/showproblem.php?pid=5880
思路:
就是先把所以需要屏蔽的串挂在AC机上跑一边,并且要记录一下该串的长度,之后定义一个函数查询,把那篇文章跑一编AC机,遇到是之前屏蔽串的末尾就把当前位比如 i+1位+=1,把【i-len+1】-1。
细节看代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define maxs 1000110
#include <string.h>
#include <queue>
#define MME(I,j) memset(I,j,sizeof(I))
using namespace std;
const int MAX=26;
int ans[maxs];
int blog[maxs];
char keyword[maxs],str1[maxs];
struct AC_autom
{
int nexts[maxs][26],fail[maxs],root,L;
bool ends[maxs];
int newnode()
{
MME(nexts[L],-1);
ends[L++]=0;
return L-1;
}
void init()
{
L=0;
MME(fail,0);
MME(ends,0);
root=newnode();
}
void Insert(char *s)
{
int i,id,p=root,len=strlen(s);
for(i=0; i<len; i++)
{
id=s[i]-'a';
if( nexts[p][id] == -1 )
nexts[p][id] = newnode();
p = nexts[p][id];
}
ends[p] = 1;
ans[p] = len;
}
void build_ac()
{
queue<int> Q;
int i,p=root;
fail[p]=root;
for(i=0; i<26; i++)
{
if( nexts[p][i] ==-1 )
nexts[p][i] = root;
else
{
fail[nexts[p][i]]=root;
Q.push(nexts[p][i]);
}
}
while(!Q.empty())
{
p=Q.front();
Q.pop();
for(i=0; i<26; i++)
{
if(nexts[p][i]==-1)
nexts[p][i]=nexts[fail[p]][i];
else
{
fail[nexts[p][i]]=nexts[fail[p]][i];
Q.push( nexts[p][i] );
}
}
}
}
void query(char *s)
{
int p=root,id,i,len=strlen(s);
for(i=0; i<len; i++)
{
if( s[i]>='a' && s[i]<='z' )
id=s[i]-'a';
else
if( s[i]>='A' && s[i]<='Z' )
id=s[i]-'A';
else
continue;
p = nexts[p][id];
int tp=p;
while( tp!=root )
{
if( ends[tp] )
{
blog[ i+1 ] -= 1;
blog[ i-ans[tp]+1 ] += 1;//为什么只标记i+1 和 i-len+1呢??因为中间的全是0啊,为了后面做准备
break;
}
tp=fail[tp];
}
}
}
}AC;
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
MME(ans,0);
MME(blog,0);
scanf("%d",&n);
//getchar();
AC.init();
for(int i=0; i<n; i++)
{
scanf("%s",keyword);
//getchar();
AC.Insert(keyword);
}
AC.build_ac();
getchar();
gets(str1);
// puts("*****************");
//puts(str1);
AC.query(str1);
int re=0,len=strlen(str1);
for(int i=0; i<len; i++)//你看哈,如果re+blog[i]>0说明该串要被屏蔽了,如果blog[i]<0那么re+=blog[i]=0,说明屏蔽结束了。读者可以好好想一下~~
{
re+=blog[i];
if( re <= 0 )
printf("%c",str1[i]);
else printf("*");
}
puts("");
//printf("%d\n",query(root));
}
return 0;
}