自动机

hdu2222(AC自动机)

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-01 08:49:14
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 87731 Accepted Submission(s): 30561 Problem Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched. To

AC自动机总结

假装没事ソ 提交于 2019-12-01 07:13:54
问题引入 考虑KMP问题的升级版,即有多个模式串,单个文本串。问匹配次数。 问题解决 暴力KMP 考虑对于每一个模式串建一个 \(fail\) 然后对于每一个模式串都和文本串暴力跑。 AC自动机 前置知识 Trie树,bfs……没什么好说的。 算法实现 我们考虑将所有的模式串放到一颗 \(Trie\) 树,如果匹配失败的话转移到 \(fail\) 指针上面去,这样子复杂度就是 \(O(n)\) 的了 。 唯一的问题在于 \(fail\) 怎么构建,直接$BFS即可。 代码实现 void insert(char *s){ int l=strlen(s),pos=0; for(int i=0;i<l;i++){ int x=s[i]-'a'; if(!ch[pos][x])ch[pos][x]=++tot; pos=ch[pos][x]; } siz[pos]++; } queue<int>Q; void get_fail(){ for(int i=0;i<26;i++) if(ch[0][i]){ Q.push(ch[0][i]);fail[ch[0][i]]=0; } while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=0;i<26;i++){ int &v=ch[u][i]; if(v){ fail[v]=ch[fail[u

190709-sugar-AC自动机/dp

夙愿已清 提交于 2019-12-01 07:13:17
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 namespace Moxing{ 8 const int N=5e6+50,inf=0x3f3f3f3f; 9 char b[N],s[N]; 10 int c[N][2],fail[N],q[N],mi[N],cnt,l,r,len,a[N],f[N],n; 11 void insert(char *s){ 12 int len=strlen(s),now=0; 13 for(int i=0;i<len;i++){ 14 int x=s[i]-'0'; 15 if(!c[now][x]) c[now][x]=++cnt; 16 now=c[now][x]; 17 } 18 mi[now]=len; 19 } 20 void build(){ 21 for(int i=0;i<2;i++){ 22 if(c[0][i]) q[++r]=c[0][i]; 23 } 24 l=1; 25 while(l<=r){ 26 int x=q[l++]; 27 for(int i=0;i<2;i++){ 28 int &y=c[x][i];

HDU-2825-Wireless Password(AC自动机, 状压DP)

旧街凉风 提交于 2019-11-30 20:03:42
链接: https://vjudge.net/problem/HDU-2825 题意: Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless network in the building. Liyuan did not know the password of the network, but he got some important information from his neighbor. He knew the password consists only of lowercase letters 'a'-'z', and he knew the length of the password. Furthermore, he got a magic word set, and his neighbor told him that the password included at least k words of the magic word set (the k words in the password possibly overlapping). For instance, say that you know that the password is

KMP自动机

♀尐吖头ヾ 提交于 2019-11-30 16:18:39
KMP自动机 分类:字符串 内容:详细版 前置知识 不会的可以点击链接(如果有)或者前往 OI-Wiki 学习 KMP 一些约定 字符集大小默认为 m 模板字符串默认为 s 文本字符串默认为 t |s| 指字符串 s 的长度 字符串下标默认从 1 开始 简介 KMP自动机主要用于字符串的匹配问题,预处理复杂度为 O(|s|*m) ,可以以严格 O(|t|) 的复杂度进行字符串匹配( KMP 为均摊 O(|t|) ) ,并且可以处理可持久化字符串匹配问题 。 同时 KMP 自动机也是 AC 自动机(可以处理多个模板串的匹配)的基础。 构造 KMP 自动机 KMP 自动机与 KMP 的区别在于 KMP 自动机额外求出了 \(trans_{i,j}\) 表示在第 i 位置上往后匹配一个 j 字符会转移到什么状态(状态在这里指已经成功匹配了多少个字符)。 在下文中,将用 fail 来代替 KMP 的 next , nxt 代替上面的 trans。 普通地实现 KMP 自动机 假设我们处理到了第 i 个状态并且前 i-1 个状态已经完全处理好了,当前的 fail 也指向了正确的位置。 考虑每个 nxt 指向的状态: nxt[s[i + 1]] 显然指向 i+1 。 其余的 nxt 应当指向一直跳 fail 后第一个下一个字符能匹配的位置,即: nxt[i][j] = i; while(nxt

【模板】后缀自动机

时光怂恿深爱的人放手 提交于 2019-11-30 12:29:21
后缀自动机是一个能够接受母串所有后缀的最简自动机。 其中,每个节点代表一个字符串集合,该集合中所有的字符串均有相同的 \(right\) 集合。 各个节点之间根据 \(right\) 集合的关系可以组织成一棵树形结构,称为 \(parent\) 树。 后缀自动机最多有 \(2*n - 1\) 个节点。 代码如下 #include <bits/stdc++.h> using namespace std; struct SAM { struct state { int len, p, cnt; map<char, int> go; state(int _len = 0, int _p = -1, int _cnt = 0) { len = _len; p = _p; cnt = _cnt; } }; int last; vector<state> t; SAM() { last = 0; t.push_back({}); } inline state& operator[](int x) { return t[x]; } inline int size() { return t.size(); } inline void extend(char c) { int cur = t.size(); t.push_back({t[last].len + 1, -1, 1}); int x =

KMP & AC自动机

痞子三分冷 提交于 2019-11-30 05:48:58
KMP 和 AC自动机 都可以解决字符串匹配问题 KMP是一对一匹配 AC自动机是多对一匹配 KMP KMP核心思想是 利用字符串的前缀与后缀相同,失配时跳到等于后缀的前缀,可以不必从头开始 。 这张图列举了字符"ABCDABD"所有的前缀和后缀 红色的表示前缀和后缀相等 例如: 用字符 P=“ABCDABCDE” 去匹配 字符 S = “ABCDABCDABCDABCD” 当匹配到 ABCDABCD ABCDABCD时 发现’A’与’E’不匹配 那指针就可以不必从头开始,可以跳到 ABCD ABCDE 从A开始匹配 原理很简单,就是因为后缀等于前缀,那么本来后缀能匹配的上的前缀依然能匹配上 现在开始构造后缀等于前缀的指针数组 (next) 这里用到了DP的思想 当计算第i个字符的next指针 去找第i-1个字符的next指针所指向的字符 要是这个字符的下一个字符等于第i个字符 那么第i个字符的next指针指向这个字符的下标 否则继续去寻找这个字符反而next指针所指向的字符(开始循环) 原理还是很简单 因为要找第i个字符next指针,第i-1个字符已经找到到它的next 所以就在第i-1个字符所构成的后缀 与之相等的前缀的后面一个去找第i个字符 code /* https://www.luogu.org/problem/P3375 P3375 【模板】KMP字符串匹配 */ #

HDU2222 Keywords Search AC自动机

泪湿孤枕 提交于 2019-11-30 04:35:09
网址: https://vjudge.net/problem/HDU-2222 题意: 统计模式串在文本串的出现次数,文本串只含有小写字母。 题解: $AC$自动机的模板题,在$Trie$树上建出$Trie$图,然后查询的时候跳$fail$指针直到已访问结点或者根结点记录数量,标记已访问结点即可。 AC代码: #include <cstring> #include <cstdio> #include <queue> using namespace std; #define maxn int(5e5+9) #define m(a,b) memset (a,b,sizeof(a)); #pragma GCC Optimize(2) int trie[maxn][26]; int cntword[maxn]; int fail[maxn]; int cnt = 0,ans=0; struct AC { void insert(char *str) { int root = 0, next; int len=strlen(str); for (int i = 0; i < len; ++i) { next = str[i] - 'a'; if (!trie[root][next]) trie[root][next] = ++cnt; root = trie[root][next]; } +

BZOJ2938:[POI2000] 病毒

落花浮王杯 提交于 2019-11-30 02:04:38
Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。 示例: 例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。 任务: 请写一个程序: l 读入病毒代码; l 判断是否存在一个无限长的安全代码; l 将结果输出 Input 第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。 Output 你应在在文本文件WIN.OUT的第一行输出一个单词: l TAK——假如存在这样的代码; l NIE——如果不存在。 Sample Input 3 01 11 00000 Sample Output NIE 思路: 首先将所有病毒串建一棵AC自动机。 想象一个无限长的安全代码存在,那么拿它到AC自动机上匹配,它会一直匹配但是一直匹配不成功。 也就是说匹配的时候不能匹配到End为1的结点(设为x),且fail指针指向终点的点(设为y)也不能匹配到,因为root.

AC自动机总结

大兔子大兔子 提交于 2019-11-29 16:47:41
KMP kmp处理题型总结 Manacher POJ - 3974 Palindrome (Manacher模板+讲解) 最大最小表示法 HDU-3374 String Problem (最小最大表示法) AC自动机 AC自动机总结 来源: https://www.cnblogs.com/Tianwell/p/11523410.html