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

吐槽

数据太水了吧,我AC自动机的trie建错了结果只是RE了两个点,还以为数组开小了改了好久

思路

看到多模板串,字符串匹配,且模板串总长度不长,就想到AC自动机
然后用栈维护当前的字符串位置,如果匹配到了,就从栈里逐个弹出对应的字符,并且回溯到匹配这个单词之前的节点
s每个字符最多会被出栈和入栈各两次,复杂度是\(O(n+m)\)

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
int trie[410000][26],Nodecnt=0,fail[410000],mark[410000],root,len[410000],n;
char s[410000],t[410000];
void insert(char *s,int len,int cnt){
    int o=root;
    for(int i=1;i<=len;i++){
        if(!trie[o][s[i]-'a'])
            trie[o][s[i]-'a']=++Nodecnt;
        o=trie[o][s[i]-'a'];    
    }
    mark[o]=cnt;
}
void build_AC(void){
    queue<int> q;
    for(int i=0;i<26;i++){
        if(trie[root][i]){
            fail[trie[root][i]]=root;
            q.push(trie[root][i]);
        }
    } 
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(trie[x][i]){
                fail[trie[x][i]]=trie[fail[x]][i];
                q.push(trie[x][i]);
            }
            else{
                trie[x][i]=trie[fail[x]][i];
            }
        }
    }  
}
struct SNode{
    int num;
    char c;
};
stack<char> S2;
stack<SNode> S1;
void query(void){
    int o=root;
    int mid=0;
    while(S2.size()){
        // printf("%d %d\n",++mid,S1.size());
        char c=S2.top();
        S2.pop();
        o=trie[o][c-'a'];
        if(!mark[o])
            S1.push((SNode){o,c});
        else{
            // printf("begin\n");
            int p=o;
            for(int i=1;i<=len[mark[p]];i++){
                if(S1.size())
                    o=S1.top().num;
                else{
                    o=root;
                    break;
                }
                if((!S1.empty())&&i<len[mark[p]])
                    S1.pop();
                else if(i<len[mark[p]]){
                    o=root;
                    break;
                }
            }
        }
    }
}
void print(void){
    char c=S1.top().c;
    S1.pop();
    if(!S1.empty())
        print();
    putchar(c);
}
int main(){
    // freopen("testdata (5).in","r",stdin);
    // freopen("test.out","w",stdout);
    scanf("%s",s+1);
    int lens=strlen(s+1);
    // printf("lens=%d\n",lens);
    // _sleep(1000);
    for(int i=lens;i>=1;i--)
        S2.push(s[i]);
    // int g=1;
    // for(;g<=lens;g++)
    //     if(s[g]!='a')
    //         break;
    // printf("sa=%d\n",g-1);
    // _sleep(1000);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",t+1);
        len[i]=strlen(t+1);
        // printf("len[%d]=%d\n",i,len[i]);
        // _sleep(1000);
        insert(t,len[i],i);
    }
    build_AC();
    query();
    // printf("ok\n");
    print();
    printf("\n");
    return 0;
}
posted @ 2019-03-01 08:45  dreagonm  阅读(150)  评论(0编辑  收藏  举报