mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
136 lines
3.1 KiB
C++
136 lines
3.1 KiB
C++
|
/*
|
|||
|
* HDU 5880 Family View
|
|||
|
* 把文本串中所有的模式串换为等长度的'*'
|
|||
|
*
|
|||
|
* AC自动机
|
|||
|
* 将模式串建立AC自动机,然后进行文本串匹配,求出文本串的每个前缀
|
|||
|
* 所包含的最长后缀,并且是模式串,用pos数组记录位置,然后扫描一遍输出即可。
|
|||
|
*/
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
#include <iostream>
|
|||
|
#include <algorithm>
|
|||
|
#include <queue>
|
|||
|
#include <vector>
|
|||
|
using namespace std;
|
|||
|
|
|||
|
const int MAXN = 1000000+100;
|
|||
|
char str[MAXN];
|
|||
|
int pos[MAXN];
|
|||
|
struct Aho_Corasick
|
|||
|
{
|
|||
|
const static int maxnode = 1000000+100;
|
|||
|
const static int type = 26;
|
|||
|
int next[maxnode][type],fail[maxnode],end[maxnode],l[maxnode];
|
|||
|
int root,L;
|
|||
|
int newnode()
|
|||
|
{
|
|||
|
for(int i = 0;i<type;i++)
|
|||
|
next[L][i] = -1;
|
|||
|
l[L]=0;
|
|||
|
end[L++] = -1;
|
|||
|
return L-1;
|
|||
|
}
|
|||
|
void init()
|
|||
|
{
|
|||
|
L = 0;
|
|||
|
root = newnode();
|
|||
|
}
|
|||
|
void insert(char* str)
|
|||
|
{
|
|||
|
int len = strlen(str);
|
|||
|
int now = root;
|
|||
|
for(int i = 0;i < len;i++)
|
|||
|
{
|
|||
|
int id=str[i]-'a';
|
|||
|
if(next[now][id] == -1)
|
|||
|
next[now][id] = newnode();
|
|||
|
now=next[now][id];
|
|||
|
}
|
|||
|
end[now]=1;
|
|||
|
l[now]=len;
|
|||
|
}
|
|||
|
void build()
|
|||
|
{
|
|||
|
queue<int>Q;
|
|||
|
fail[root] = root;
|
|||
|
for(int i = 0;i < type;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 < type;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]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void work(char* str)
|
|||
|
{
|
|||
|
int id;
|
|||
|
int len = strlen(str);
|
|||
|
int now = root;
|
|||
|
memset(pos,0,sizeof(pos));
|
|||
|
for(int i = 0;i < len;i++)
|
|||
|
{
|
|||
|
if(str[i]>='A'&&str[i]<='Z') id=str[i]-'A';
|
|||
|
else if(str[i]>='a'&&str[i]<='z') id=str[i]-'a';
|
|||
|
else continue;
|
|||
|
now = next[now][id];
|
|||
|
int temp=now;
|
|||
|
while(temp != root)
|
|||
|
{
|
|||
|
if(end[temp] != -1)
|
|||
|
{
|
|||
|
pos[i+1]-=1;
|
|||
|
pos[i-l[temp]+1]+=1;
|
|||
|
break;
|
|||
|
}
|
|||
|
temp = fail[temp];
|
|||
|
}
|
|||
|
}
|
|||
|
long long cnt=0;
|
|||
|
for(int i=0;i<len;i++)
|
|||
|
{
|
|||
|
cnt+=pos[i];
|
|||
|
if(cnt<=0) printf("%c",str[i]);
|
|||
|
else printf("*");
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
}
|
|||
|
}AC;
|
|||
|
|
|||
|
int main()
|
|||
|
{
|
|||
|
int T;
|
|||
|
int n;
|
|||
|
scanf("%d",&T);
|
|||
|
while(T--)
|
|||
|
{
|
|||
|
AC.init();
|
|||
|
scanf("%d",&n);
|
|||
|
for(int i=1;i<=n;i++)
|
|||
|
{
|
|||
|
scanf("%s",str);
|
|||
|
AC.insert(str);
|
|||
|
}
|
|||
|
AC.build();
|
|||
|
getchar();
|
|||
|
gets(str);
|
|||
|
AC.work(str);
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|