记录一个菜逼的成长。。
题目链接
题目大意:
有n个只包含小写字母的字符串。给你一个字符串T。如果n个字符串里存在字符串在T里,就将这个字符串在T里标记为*。(忽略大小写)
笔记
算是比较裸的AC自动机。
由n个字符串构建AC自动机。
匹配一遍,记录起始位置,然后循环标记即可。
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define clr clear()
#define cl(a,b) memset(a,b,sizeof a)
const int maxn = 1000000 + 10;
typedef long long LL;
typedef pair<int,int> PII;
vector<PII>a;
struct Trie
{
int next[1000010][26],fail[1000010],end[1000010],deep[maxn];
int root,L;
int newnode()
{
for(int i = 0;i < 26;i++)
next[L][i] = -1;
end[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
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'];
}
end[now]++;
deep[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++)
{
now = next[now][buf[i]-'a'];
int temp = now;
while( temp != root )
{
res += end[temp];
if (end[temp]) {
a.pb(mp(i-deep[temp],i));//重点
}
temp = fail[temp];
}
}
return res;
}
}ac;
char str[maxn];
bool vis[maxn];
int main()
{
int T;scanf("%d",&T);
while(T--) {
ac.init();a.clr;
int n;scanf("%d\n",&n);
for (int i = 1; i <= n; i++) {
gets(str);
ac.insert(str);
}
ac.build();
gets(str);cl(vis,false);
for (int i = 0; str[i]; i++) {
if(isupper(str[i]))vis[i] = true;
str[i] = tolower(str[i]);
}
ac.query(str);
for (auto x : a) {
for (int i = x.fi + 1; i <= x.se; i++)
str[i] = '*';
}
for (int i = 0; str[i]; i++) {
if(vis[i]) {
if(str[i] != '*')putchar(toupper(str[i]));
else putchar(str[i]);
}
else putchar(str[i]);
}
puts("");
}
return 0;
}