Censoring (Gold)(AC自动机多字符串匹配+栈)

Censoring (Gold)

题意:给了一段文本串,再给了含 N N N个字符串的字典。将文本从左到右,如果遇到了字典中的字符串,则删去这一段文本,继续按顺序匹配,输出最终文本剩下的内容。

思路:

  1. 用字典建立好AC自动机,处理出每个节点所能代表的字典中的最长字符串的长度(用topo排序处理)
  2. 将文本串在AC自动机上跑,并将每次的节点放到栈里面;如果匹配成功了,则在栈中弹出此长度的个数,并且指针移动到新的top在AC自动机上的pos

题目描述

//#pragma comment(linker, "/STACK:102400000,102400000")
#include "bits/stdc++.h"
#define pb push_back
#define ls l,m,now<<1
#define rs m+1,r,now<<1|1
#define rt 1,n,1
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}

const int maxn = 1e5+10;
const int mod = 1e9+7;
const double eps = 1e-9;

char s[maxn], t[maxn];
int trie[maxn][26], fail[maxn];
int pos[maxn], stk[maxn], ed[maxn], in[maxn];
int tot, top;
vector<int> refail[maxn];

void insert() {
    int len=strlen(t), p=0;
    for(int i=0; i<len; ++i) {
        int k=t[i]-'a';
        if(!trie[p][k]) trie[p][k]=++tot;
        p=trie[p][k];
    }
    ed[p]=len;
}

void build() {
    queue<int> q;
    for(int i=0; i<26; ++i) if(trie[0][i]) q.push(trie[0][i]);
    while(q.size()) {
        int now=q.front(); q.pop();
        for(int i=0; i<26; ++i) {
            if(trie[now][i]) {
                fail[trie[now][i]]=trie[fail[now]][i];
                in[trie[now][i]]++;
                refail[trie[now][i]].pb(trie[fail[now]][i]);
                q.push(trie[now][i]);
            }
            else trie[now][i]=trie[fail[now]][i];
        }
    }
}

void topo() {
    queue<int> q;
    for(int i=0; i<=tot; ++i) if(!in[i]) q.push(i);
    while(q.size()) {
        int now=q.front(); q.pop();
        for(auto p: refail[now]) {
            ed[p]=max(ed[p],ed[now]);
            if(--in[p]==0) q.push(p);
        }
    }
}

void solve() {
    int len=strlen(s), p=0;
    for(int i=0; i<len; ++i) {
        stk[++top]=i;
        int k=s[i]-'a';
        p=trie[p][k];
        if(ed[p]) top-=ed[p], p=pos[stk[top]];
        pos[stk[top]]=p;
    }
}

int main() {
    //ios::sync_with_stdio(false); cin.tie(0);
    scanf("%s", s);
    int N=read();
    for(int i=0; i<N; ++i) scanf("%s", t), insert();
    build();
    solve();
    for(int i=1; i<=top; ++i) putchar(s[stk[i]]);
    puts("");
}
全部评论

相关推荐

06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
05-12 22:16
已编辑
北京邮电大学 研发工程师
牛客30236098...:0offer+1 滴滴都不给我面 佬没投鹅吗,鹅应该很喜欢北邮吧
投递美团等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务