zoukankan      html  css  js  c++  java
  • BZOJ_3940_[Usaco2015 Feb]Censoring_AC自动机

    BZOJ_3940_[Usaco2015 Feb]Censoring_AC自动机

    Description

    FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S。他有一个包含n个单词的列表,列表里的n个单词
    记为t_1...t_N。他希望从S中删除这些单词。 
    FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中
    没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词 
    FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的 
    请帮助FJ完成这些操作并输出最后的S

    Input

    第一行包含一个字符串S 
    第二行包含一个整数N 
    接下来的N行,每行包含一个字符串,第i行的字符串是t_i

    Output

    The string S after all deletions are complete. It is guaranteed that S will not become empty during the deletion process.
    一行,输出操作后的S
     

    Sample Input

    begintheescapexecutionatthebreakofdawn
    2
    escape
    execution

    Sample Output

    beginthatthebreakofdawn

    首先是要对单词建立AC自动机。
    然后用一个栈记录答案和匹配到哪个点。
    因为题里说不会有一个单词会是另一个单词的子串,于是遇到被标记的结点就弹栈即可。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 200050
    int ch[N][26],cnt=1,fail[N],flg[N],n,S[N],Q[N],l,r,len[N],ans[N];
    char w[N],s[N];
    void insert(int x) {
    	int p=1,i;
    	for(i=1;w[i];i++) {
    		int &k=ch[p][w[i]-'a'];
    		if(!k) k=++cnt;
    		p=k;
    	}
    	flg[p]=x;
    }
    void build() {
    	int i,p;
    	for(i=0;i<26;i++) ch[0][i]=1;
    	Q[r++]=1;
    	while(l<r) {
    		p=Q[l++];
    		for(i=0;i<26;i++) {
    			if(ch[p][i]) fail[ch[p][i]]=ch[fail[p]][i],Q[r++]=ch[p][i];
    			else ch[p][i]=ch[fail[p]][i];
    		}
    	}
    }
    int main() {
    	scanf("%s%d",s+1,&n);
    	int ls=strlen(s+1);
    	int i;
    	for(i=1;i<=n;i++) {
    		scanf("%s",w+1); insert(i); len[i]=strlen(w+1);
    	}
    	build();
    	// puts("FUCK");
    	int p=1;
    	for(i=1;i<=ls;i++) {
    		p=ch[p][s[i]-'a'];
    		S[++S[0]]=p; ans[S[0]]=s[i];
    		if(flg[p]) S[0]-=len[flg[p]],p=S[S[0]];
    	}
    	for(i=1;i<=S[0];i++) {
    		printf("%c",ans[i]);
    	}
    }
    
  • 相关阅读:
    小小的疑问和小小的想法
    为什么你的代码不能给别人看?
    linux之中对文件名和文件进行编码转换
    数据泵导入导出步骤
    杭电acm1266
    杭电acm2097
    杭电acm2019
    杭电acm1395(转自牛人代码)
    杭电acm1279
    杭电acm1412
  • 原文地址:https://www.cnblogs.com/suika/p/9079130.html
Copyright © 2011-2022 走看看