题目大意:给出n个模式串,一个文本串,把文本串中所有模式串中存在的子串变成’*’
后就没写自动机了,这次是理解着写出来的,感觉很不错。
对模式串建自动机,匹配的时候当匹配到一个模式串,标记一下。
需要注意的是每一个节点记录一下该节点结尾的最长模式串(也可以说是后缀)这个在建fail树的时候做就行。
否则这种数据没法过
1
2
abcd
bc
abc
匹配的时候会匹配abcd模式串,并且不会出现失配,也就是不会倒bc那条路上,但这样bc就不会被标记,因此建立fail的时候在abcd的c上标记2。即最长的以c结尾的模式串长为2
代码如下:
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <ctime>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-8;
const int maxn = 1123456;
struct Node
{
int next[26],fail,len;
int f;
} nd[maxn];
char str[maxn];
char ps[maxn];
int tp;
int NewNode()
{
memset(nd[tp].next,-1,sizeof(nd[tp].next));
nd[tp].f = 0;
nd[tp].fail = -1;
return tp++;
}
void Add(int root)
{
for(int i = 0; ps[i]; ++i)
{
int k = ps[i]-'a';
if(nd[root].next[k] == -1) nd[root].next[k] = NewNode();
nd[nd[root].next[k]].len = nd[root].len+1;
root = nd[root].next[k];
}
nd[root].f = nd[root].len;
}
void Build(int root)
{
queue <int> q;
q.push(root);
nd[root].fail = 0;
while(!q.empty())
{
root = q.front();
//printf("%d %d\n",root,nd[root].fail);
nd[root].f = max(nd[root].f,nd[nd[root].fail].f);
q.pop();
for(int i = 0; i < 26; ++i)
{
if(nd[root].next[i] == -1) continue;
if(!root)
{
nd[nd[root].next[i]].fail = 0;
}
else
{
int tmp = nd[root].fail;
while(tmp && nd[tmp].next[i] == -1) tmp = nd[tmp].fail;
nd[nd[root].next[i]].fail = nd[tmp].next[i] != -1? nd[tmp].next[i]: 0;
}
q.push(nd[root].next[i]);
}
}
}
int pos[maxn];
void solve(int root)
{
int k;
memset(pos,-1,sizeof(pos));
for(int i = 0; str[i]; ++i)
{
if('A' <= str[i] && str[i] <= 'Z') k = str[i]-'A';
else if('a' <= str[i] && str[i] <= 'z') k = str[i]-'a';
else
{
root = 0;
continue;
}
while(root && nd[root].next[k] == -1)
root = nd[root].fail;
if(nd[root].next[k] != -1)
root = nd[root].next[k];
if(nd[root].f)
{
pos[i-nd[root].f+1] = i;
}
}
int en = -1;
for(int i = 0; str[i]; ++i)
{
en = max(en,pos[i]);
if(i <= en) putchar('*');
else putchar(str[i]);
}
puts("");
}
int main()
{
//fread("in.in");
//fwrite("my.out");
int t,n;
char ch;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
tp = 0;
int root = NewNode();
nd[root].len = 0;
nd[root].f = 0;
while(n--)
{
scanf("%s",ps);
Add(root);
}
Build(root);
while(ch = getchar() != '\n');
gets(str);
solve(root);
}
return 0;
}