zoukankan      html  css  js  c++  java
  • P3121 [USACO15FEB]审查(黄金)Censoring (Gold)

    P3121 [USACO15FEB]审查(黄金)Censoring (Gold)

    思路:

    首先构造AC自动机,然后那串去匹配,并且记录一下每一个字符匹配时在AC自动机上的位置。
    如果成功匹配一个单词,那么就需要从串中删除这个单词,并且从之前标记的位置开始匹配。
    因为单词的长度我们知道,所以直接利用一个数组模拟的栈来搞就行。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    int n,top;
    char s[N],t[N];
    int sta[N];
    int Skip[N];
    queue <int> q;
    struct Aho_Corasick{
        int Size;
        int ch[N][30];
        int val[N];
        int fail[N];
        void init(){
            Size=-1;
            newnode();
        }
        int newnode(){
            memset(ch[++Size],0,sizeof(ch[0]));
            val[Size]=fail[Size]=0;
            return Size;
        }
        void insert(char *s){
            int l=strlen(s);
            int u=0;
            for(int i=0;i<l;i++){
                int idx=s[i]-'a';
                if(!ch[u][idx]) ch[u][idx]=newnode();
                u=ch[u][idx];
            }
            val[u]=l;
        }
        void Getfail(){
            while(!q.empty()) q.pop();
            for(int i=0;i<26;i++){
                if(ch[0][i]) q.push(ch[0][i]);
            }
            while(!q.empty()){
                int cur=q.front();q.pop();
                for(int i=0;i<26;i++){
                    if(ch[cur][i]){
                        fail[ch[cur][i]]=ch[fail[cur]][i];
                        q.push(ch[cur][i]);
                    }else{
                        ch[cur][i]=ch[fail[cur]][i];
                    }
                }
            }
        }
        void query(char *s){
            int l=strlen(s);
            int u=0;
            for(int i=0;i<l;i++){
                int idx = s[i]-'a';
                sta[++top]=i;
                int cur = ch[u][idx];
                Skip[top]=cur;
                if(val[cur]){
                    //cout<<top<<" "<<val[cur]<<endl;
                    top-=val[cur];
                    u=Skip[top];
                    continue ;
                }
                u=cur;
            }
        }
    }ac;
    int main(){
        //freopen("testdata.in","r",stdin);
        //freopen("testdate",)
        scanf("%s",s);
        scanf("%d",&n);
        ac.init();
        for(int i=1;i<=n;i++){
            scanf("%s",t);
            ac.insert(t);
        }
        ac.Getfail();
        ac.query(s);
        for(int i=1;i<=top;i++) printf("%c",s[sta[i]]);
        printf("
    ");
        return 0;
    }
    /*
    abbababaab
    3
    baa
    bab
    aab
    */
    
    
    
  • 相关阅读:
    chown更改文件和目录的所有者
    常量指针和指向常量的指针
    声明,有人破解我的mmsplayer,声称开源的mms
    声明,有人破解我的mmsplayer,声称开源的mms
    慎用mysql的utf8unicode
    慎用mysql的utf8unicode
    在 Ubuntu 下使用 Android NDK r4b 编译 FFmpeg 0.6.3
    skia 生成 vs2008工程
    mmsPlayer 2.0 将开源java部分
    skia 生成 vs2008工程
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10877743.html
Copyright © 2011-2022 走看看