您的位置:首页 > 其它

HDU5880 Family View(AC自动机)

2016-10-10 18:30 218 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5880

题意:给定N个串,一个长文本,把那N个串在长文本里出现的部分用×代替。

思路:把N个串放到AC自动机上然后在结点标记上串长,接着把长文本放到自动机上去匹配,匹配到了就替换掉。

至于替换的方法,不用暴力的去修改,只要同类似括号匹配的方式打上标记就好了。要注意2种情况的处理

1:   N个串种有 abcd,bcde这种交叉的情况

2:  N个串有 abcd bc这种包含的情况

然后,千万不要memset整个数组,因为测评鸡算内存只会算用过的,一memset就算全用过了,会爆内存,要用一个就初始化一个。

代码:

#include <bits/stdc++.h>

using namespace std;

#define fur(i,a,b) for(int i=(a);i<=(b);i++)
#define furr(i,a,b) for(int i=(a);i>=(b);i--)
#define cl(a) memset((a),0,sizeof(a))

typedef long long ll;

const int maxsz = 1000000;

const int maxn = 1010000;
int cg[maxn];

char str[maxsz+10];

struct AC
{
struct Node
{
int fail,cnt,next[26];
}node[maxn+10];

int sz;
queue<int>q;

void init(){
sz = 0;
newnode();
while(!q.empty()) q.pop();
}

int newnode(){
cl(node[sz].next);
node[sz].fail = 0;
node[sz].cnt = 0;
return sz++;
}

void insert(char *s){
int len = strlen(s);
int now = 0;
for(int i = 0; i < len; ++i){
char c = s[i];
if(!node[now].next[c-'a'])
node[now].next[c-'a'] = newnode();
now = node[now].next[c-'a'];
}
node[now].cnt = len;
}

void build(){
node[0].fail = -1;
q.push(0);
while(!q.empty()){
int u = q.front();
q.pop();
fur(i,0,25){
if(node[u].next[i]){
if(u == 0)
node[node[u].next[i]].fail = 0;
else{
int v = node[u].fail;
while(v!=-1){
if(node[v].next[i]){
node[node[u].next[i]].fail = node[v].next[i];
break;
}
v = node[v].fail;
}
if(v == -1) node[node[u].next[i]].fail = 0;
}
q.push(node[u].next[i]);
}
}
}
}

void getret(int u, int i){
while(u){
if(node[u].cnt){
cg[i+1]++;
cg[i-node[u].cnt+1]--;
}
u = node[u].fail;
}
}

void match(char *s){
cl(cg);
int len = strlen(s);
int now = 0;
for(int i = 0; i < len; ++i){
int idx;
if(s[i]>='A'&&s[i]<='Z') idx=s[i]-'A';
else if(s[i]>='a'&&s[i]<='z') idx=s[i]-'a';
else{
now = 0;
continue;
}
if(node[now].next[idx])
now = node[now].next[idx];
else{
int u = node[now].fail;
while(u!=-1 && !node[u].next[idx]) u = node[u].fail;
if(u == -1) now = 0;
else now = node[u].next[idx];
}
getret(now,i);
}

int tmp = 0;

for(int i = 0; i < len; ++i){
tmp+=cg[i];
if(tmp<0) putchar('*');
else putchar(s[i]);
}
puts("");
}

}ac;

int main(){
int T;
scanf("%d",&T);
while(T--){
ac.init();
int n;
scanf("%d",&n);
while(n--){
scanf("%s",str);
ac.insert(str);
}
ac.build();
getchar();
gets(str);
ac.match(str);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: