AC自动机——Luogu3121 [USACO15FEB]审查(黄金)Censoring (Gold)

https://www.luogu.org/problem/show?pid=3121
这题嘛。。。AC自动机
我们在匹配的时候可以开一个栈,一开始栈内为空,匹配时依次加入字母的位置,当匹配完成时把这个单词弹出继续操作就好了
其他没啥变化
具体看这段代码啦

inline void getans(int l){
    int now=0;
    for(int i=1;i<=l;i++){
        now=p[now][s[i]-'a'];
        pr[++sum]=now;rp[sum]=i;
        if(b[now]){//以下下弹栈操作
            sum-=b[now];
            now=pr[sum];
        }
    }
}

好像被数据坑了,据lc233说,按照一开始的bfs求fail写法会超时。。。
所以换了一个模板。。。
不多说,上代码吧

#include<bits/stdc++.h>
using namespace std;
char s[100001],c[100001];
int n,np=0,q[100001],p[100001][26],fail[100001];
int rp[100001],pr[100001],b[100001],sum=0;
inline void insert(){
    int now=0,l=strlen(c+1);
    for(int i=1;i<=l;i++){
        int t=c[i]-'a';
        if(!p[now][t])p[now][t]=++np;
        now=p[now][t];
    }
    b[now]=l;
}
inline void bfs(){
    int l,r;l=r=0;
    for(int i=0;i<26;i++)if(p[0][i])q[++r]=p[0][i];
    while(l<r){
        l++;
        int t=q[l];
        for(int i=0;i<26;i++)if(!p[t][i])p[t][i]=p[fail[t]][i];
        else{
            q[++r]=p[t][i];
            fail[p[t][i]]=p[fail[t]][i];
        }
    }
}
inline void getans(int l){
    int now=0;
    for(int i=1;i<=l;i++){
        now=p[now][s[i]-'a'];
        pr[++sum]=now;rp[sum]=i;
        if(b[now]){
            sum-=b[now];
            now=pr[sum];
        }
    }
}
int main()
{
    scanf("%s",s+1);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%s",c+1),insert();
    bfs();
    int l=strlen(s+1);getans(l);
    for(int i=1;i<=sum;i++)printf("%c",s[rp[i]]);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值