[bzoj3940][Usaco2015 Feb]Censoring

最近做题成双成对?不是双倍经验就是两题同解。

3940    3942

给定字典,给定字符串,删去字符串中所有字典内单词。保证不会出现二者包含状况。$n \leq 1e5,\sum len \leq 1e5$

AC自动机裸题。build出AC自动机后从左到右插入文本串,同时边匹配边push进栈里。匹配成功就弹栈。

注意要记录匹配到第几个字符的时候,AC自动机指针(我管那个一直蹦的东西就叫指针了?)指到哪里。弹栈之后要指针也要跳回来。

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> P;
const int N=100010;
struct ACAM{
    int ch[N][26],cnt[N],f[N];
    int sz,rt;
    void init(){
        memset(ch,-1,sizeof ch);
        memset(cnt,0,sizeof cnt);
        memset(f,0,sizeof f);
        sz=rt=0;
    }
    void ins(char *s){
        int n=strlen(s),u=rt;
        for(int i=0;i<n;i++){
            int c=s[i]-'a';
            if(!~ch[u][c])
            ch[u][c]=++sz;
            u=ch[u][c];
        }
        cnt[u]=n;
    }
    void build(){
        queue<int>q;
        while(!q.empty())q.pop();
        for(int i=0;i<26;i++)
        if(~ch[rt][i])
        f[ch[rt][i]]=rt,q.push(ch[rt][i]);
        else ch[rt][i]=rt;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++){
                int v=ch[u][i];
                if(~v){
                    int now=f[u];
                    while(f&&!~ch[now][i])now=f[now];
                    f[v]=ch[now][i];q.push(v);
                }
                else ch[u][i]=ch[f[u]][i];
            }
        }
    }
    void query(char *s){
        int n=strlen(s);
        stack<P>S;int u=0;
        while(!S.empty())S.pop();
        for(int i=0;i<n;i++){
            int c=s[i]-'a';
            while(u&&!~ch[u][c])u=f[u];
            u=ch[u][c];S.push(P(c,u));
            if(cnt[u]){
                for(int j=1;j<=cnt[u];j++)
                S.pop();
                if(!S.empty())u=S.top().y;
                else u=0;
            }
        }
        vector<char>ans;
        while(!S.empty())
        ans.push_back(S.top().x+'a'),S.pop();
        for(int i=ans.size()-1;~i;i--)
        printf("%c",ans[i]);
    }
}Aho;
char str[N],s[N];
int main(){
    scanf("%s",str);
    int n;scanf("%d",&n);
    Aho.init();
    for(int i=1;i<=n;i++){
        memset(s,0,sizeof s);
        scanf("%s",s);
        Aho.ins(s);
    }
    Aho.build();
    Aho.query(str);
}

 

posted @ 2017-12-23 19:37  orzzz  阅读(153)  评论(0编辑  收藏  举报