P3121 [USACO15FEB]Censoring G(AC自动机+STL)

传送门
洛谷的标签和题解都说这题需要用栈,但其实用一个记忆数组pre+string类的earse函数就够了.只需要每次跑到可以删除的状态,直接删然后跑回pre[i-len]就可以了.
代码

#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>

using namespace std;
const int N = 4e5+10;

inline int read(){
    int x = 0,f=1;char ch = getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

namespace Auto{
    int trie[26][N],fail[N],fa[N],tot,dep[N],p,ed[N],tt[26][N],pre[N];
    vector<pii> vec;
    void ins(string s){
        p = 0;
        int dp = 1;
        for(auto x:s){
            int ch = x - 'a';
            if(!trie[ch][p]) fa[++tot] = p,dep[tot] = dp,trie[ch][p] = tot,tt[ch][p] = tot;
            p = trie[ch][p];
            dp++;
        }
        ed[p] = 1;
    }
    void bfs(){
        queue<int> q;
        fir(i,0,25) if(trie[i][0]) q.push(trie[i][0]);
        while(q.size()){
            int p = q.front();q.pop();
            fir(i,0,25){
                int fl = fail[p];
                if(trie[i][p]) fail[trie[i][p]] = trie[i][fl],q.push(trie[i][p]);
                else trie[i][p] = trie[i][fl];
            }
        }
    }
    void dfs(string &s){
        p = 0;
        fir(i,0,(int)s.size()-1){
            char x = s[i];
            int ch = x - 'a';
            p = trie[ch][p];
            if(ed[p]){
                int len = dep[p];
                s.erase(i-len+1,len);
                p = pre[i-len];
                i = i-len;
                pre[i] = p;
                continue;
            }
            pre[i] = p;
        }
    }
}
using namespace Auto;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    string str,s;
    cin >> str; 
    int n;
    cin >> n;
    fir(i,1,n){
        cin >> s;
        ins(s);
    }
    bfs();
    dfs(str);
    cout << str << "\n";
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值