首页 > 代码库 > bzoj3940
bzoj3940
AC自动机
复习一下。。。 可惜又写错了
我们发现就是把单词建成ac自动机,然后把串在ac自动机上跑一遍,每到一个单词结束点就删除,删除是利用栈,每次弹出单词长度个字符就可以了
发现两个小问题,strlen很慢,不能写在循环里,danger必须在构造fail时全部传递好,否则在匹配时跑fail会达到n^2
至于这里danger为什么不转移,我也不是很清楚。。。大概是因为使用了trie图优化,并且不是统计单词出现次数,只是希望尽量找到靠前的单词删除
#include<bits/stdc++.h> using namespace std; const int N = 100010; int n, top; char s[N], t[N], st[N]; int mark[N], last[N]; struct AC { int root, cnt; int danger[N], child[N][27], fail[N]; void insert() { int now = root, len = strlen(t); for(int i = 0; i < len; ++i) { int p = t[i] - ‘a‘; if(child[now][p] == 0) child[now][p] = ++cnt; now = child[now][p]; } danger[now] = strlen(t); } void build_fail() { queue<int> q; for(int i = 0; i < 26; ++i) if(child[root][i]) q.push(child[root][i]); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = 0; i < 26; ++i) { if(child[u][i] == 0) child[u][i] = child[fail[u]][i]; else { fail[child[u][i]] = child[fail[u]][i]; q.push(child[u][i]); } } } } void put_string() { int now = root, len = strlen(s); for(int i = 0; i < len; ++i) { st[++top] = s[i]; now = child[now][s[i] - ‘a‘]; last[top] = now; top -= danger[now]; now = last[top]; } } } ac; int main() { scanf("%s%d", s, &n); for(int i = 1; i <= n; ++i) { scanf("%s", t); ac.insert(); } ac.build_fail(); ac.put_string(); int cnt = 0; for(int i = 1; i <= top; ++i) printf("%c", st[i]); return 0; }
bzoj3940
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。