zoukankan      html  css  js  c++  java
  • USACO 2015 February Contest Gold T2: Censoring

    题目大意

    FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S。他有一个包含n个单词的列表,列表里的n个单词记为t1...tN。他希望从S中删除这些单词。

    FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词

    FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的

    请帮助FJ完成这些操作并输出最后的S

    题目分析

    我们通过观察,容易得出我们要做的是多模式串匹配,考虑使用AC自动机。

    用两个栈分别记录扫到当前字符x,一个记录当前栈内的所有字符,另一个对应记录这些字符在AC自动机上的位置(节点号)。

    当我们走到一个可行节点时,把两个栈都弹出 当前节点表示的模式串的长度 个元素,相当于题目中的删除操作。这样一边下来即可得到答案。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN=1e5+10;
     4 
     5 char s[MAXN],word[MAXN];
     6 int n,top;
     7 int sta[MAXN],sgn[MAXN];
     8 struct AC_Automation{
     9     int tot;
    10     int Trie[MAXN][27],fail[MAXN],num[MAXN];
    11     
    12     inline void Insert(char *s){
    13         int p=0,len=strlen(s);
    14         for(int i=0,x;i<len;++i){
    15             x=s[i]-'a';
    16             if(!Trie[p][x]) Trie[p][x]=++tot;
    17             p=Trie[p][x];
    18         }
    19         num[p]=len;
    20     }
    21     inline void Make_Fail(){
    22         queue<int> q;
    23         for(int i=0;i<26;++i)
    24             if(Trie[0][i])
    25                 q.push(Trie[0][i]);
    26         while(!q.empty()){
    27             int x=q.front();q.pop();
    28             for(int i=0;i<26;++i){
    29                 if(!Trie[x][i]){
    30                     Trie[x][i]=Trie[fail[x]][i];
    31                     continue;
    32                 }
    33                 fail[Trie[x][i]]=Trie[fail[x]][i];
    34                 q.push(Trie[x][i]);
    35             }
    36         }
    37     }
    38     inline void Solve(char *s){
    39         int p=0,x,len=strlen(s),i=0;
    40         while(i<len){
    41             x=s[i]-'a';
    42             p=Trie[p][x];
    43             sgn[++top]=p;
    44             sta[top]=i;
    45             if(num[p]){
    46                 top-=num[p];
    47                 if(!top) p=0;
    48                 else p=sgn[top];
    49             }
    50             ++i;
    51         }
    52         
    53     }
    54 }AC; 
    55 
    56 int main(){
    57     scanf("%s%d",s,&n);
    58     for(int i=1;i<=n;++i){
    59         scanf("%s",word);
    60         AC.Insert(word);
    61     }
    62     AC.Make_Fail();
    63     AC.Solve(s);
    64     for(int i=1;i<=top;++i)
    65         printf("%c",s[sta[i]]);
    66     return 0;
    67 }
  • 相关阅读:
    [转]微服务架构
    [转]认识JWT
    [转]win10中安装JDK8以及环境配置
    [转]PHP开发者必须了解的工具—Composer
    [转]php,使用Slim和Medoo搭建简单restful服务
    [转]分别使用Node.js Express 和 Koa 做简单的登录页
    [转]Node.js框架对比:Express/Koa/Hapi
    centos rancher 通过本机 docker images 新增container
    [转]Ubuntu18.04下使用Docker Registry快速搭建私有镜像仓库
    [转]rancher 初步
  • 原文地址:https://www.cnblogs.com/LI-dox/p/11214056.html
Copyright © 2011-2022 走看看