ac自动机

【AC自动机】单词

和自甴很熟 提交于 2019-11-27 14:12:37
【题目链接】 https://loj.ac/problem/10060 【题意】 某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。 【题解】 与AC自动机模板题3类似,但是这个题目记录的子串是不能重叠的。 利用下标从后往前历遍,然后把对应的位置的地方叠加到公共后缀。原因是:如果该单词出现过,那么对应的公共后缀肯定也出现过。 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N = 1005; 5 const int M = 1e6+10; 6 char S[N][205]; 7 int Trie[M][26],fail[M],End[M],Sz[M]; 8 int Q[M],Head,Tail; 9 int head[M],nxt[M],to[M],cnt; 10 int n,idx=1; 11 12 void Add_edge(int u,int v); 13 void dfs(int u); 14 void Insert( char s[] , int Id){ 15 int p = 1 ; 16 for(int i=0;s[i];i++){ 17 int t = s[i] - 'a' ; 18 if(

【AC自动机】洛谷三道模板题

非 Y 不嫁゛ 提交于 2019-11-27 14:10:06
【题目链接】 https://www.luogu.org/problem/P3808 【题意】 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。 【题解】 不再介绍基础知识了,就是裸的模板题,直接贴上来。 【代码】 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N = 5e5+100; 7 const int M = 1e6+10; 8 queue < int > Q ; 9 typedef struct Aho_Corasick_Automaton{ 10 int Son[N][26],End[N],Fail[N],idx; 11 void Init(){ 12 idx = 0 ; 13 while( !Q.empty() ) Q.pop() ; 14 memset(Son , 0 , sizeof Son ); 15 memset(End , 0 , sizeof End ); 16 memset(Fail, 0 , sizeof Fail ); 17 } 18 void Insert(char s[]){ 19 int p = 0 ; 20 for(int i=0;s[i];i++)

【AC自动机】Keywords Search

ε祈祈猫儿з 提交于 2019-11-27 14:09:59
【题目链接】 https://loj.ac/problem/10057 【题意】 原题来自: HDU 2222 给定 n 个长度不超过 50 的由小写英文字母组成的单词准备查询,以及一篇长为 m 的文章,问:文中出现了多少个待查询的单词。多组数据。 【题解】 模板题 【代码】 1 #pragma GCC optimize(2) 2 3 #include<queue> 4 #include<cstdio> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 using namespace std; 9 const int N = 5e5+1e4; 10 const int M = 1e6+10; 11 queue < int > Q ; 12 typedef struct Aho_Corasick_Automaton{ 13 int Son[N][26],End[N],Fail[N],idx; 14 void Init(){ 15 idx = 0 ; 16 while( !Q.empty() ) Q.pop() ; 17 memset(Son , 0 , sizeof Son ); 18 memset(End , 0 , sizeof End ); 19 memset(Fail, 0 , sizeof

ac自动机(加强版)

早过忘川 提交于 2019-11-27 10:57:34
题目描述 有 NN N个由小写字母组成的模式串以及一个文本串 TT T。每个模式串可能会在文本串中出现多次。你需要找出 哪些 模式串在文本串 TT T中出现的次数最多。 输入格式 输入含多组数据。 每组数据的第一行为一个正整数 NN N,表示共有 NN N个模式串, 1≤N≤1501 \leq N \leq 150 1 ≤ N ≤ 1 5 0。 接下去 NN N行,每行一个长度小于等于 7070 7 0的模式串。下一行是一个长度小于等于 10610^6 1 0 6的文本串 TT T。 输入结束标志为 N=0N=0 N = 0。 输出格式 对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。 输入输出样例 输入 #1 2 aba bab ababababac 6 beta alpha haha delta dede tata dedeltalphahahahototatalpha 0 输出 #1 4 aba 2 alpha haha这题跟上一题不太一样,这题需要求的每个模式串块出现在文本串中的次数(出现次数)输出最多次数和该模式串(可能有多个),而上一题是询问文本串中出现了几个模式串(出现即可)主要区别:在于color记上有点变动,因为还要输出模式串,再对每个模式串根据color进行insearch一下就ok #include

ac自动机(tree+kmp模板)

橙三吉。 提交于 2019-11-27 10:56:07
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 85955 Accepted Submission(s): 29888 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 simplify the problem, giving you a description of image,

ac自动机模板

╄→尐↘猪︶ㄣ 提交于 2019-11-27 05:09:10
易理解版本: // http://acm.hdu.edu.cn/showproblem.php?pid=2222 #include<bits/stdc++.h> using namespace std; const int maxn = 1e6 + 10; struct Tri { int ch[maxn][26], val[maxn], fail[maxn], sz; void init() { memset(ch[0], 0, sizeof(ch[0])); sz = 0; } void insert(char *s) { int o = 0; for (int i = 0; s[i]; i++) { int c = s[i] - ‘a’; if (!ch[o][c]) { //建立新节点 ch[o][c] = ++sz; val[sz] = 0; memset(ch[sz], 0, sizeof(ch[sz])); } o = ch[o][c]; } val[o]++; } void build() { queue q; for (int i = 0; i < 26; i++) if (ch[0][i]) { q.push(ch[0][i]); fail[ch[0][i]] = 0;//第一层节点fail都指向根 } while (!q.empty()) { int o =

AC自动机(无指针)

我们两清 提交于 2019-11-26 22:34:18
哈哈哈哈哈哈哈我终于改完这个板了啊……目前要学的字符串算法好像差不多了。 思路 其实就是在一颗Trie树上把多个字符串用类似于next数组的fail指针连成一个大的KMP。 总而言之就是让被匹配的那一长串不停地往前匹配而不退回,然后就跳来跳去的咯,原理是和KMP一样的。更好地理解fail指针和如何实现移步https://blog.csdn.net/u013371163/article/details/60469145,不过博主写得实在是太可爱了=v=。 JZOJ1566 单词查找 Description 给一个主串S以及M个字符串。问这M个字符串在主串中出现多少次。 Input 第一行一个整数N,表示S的长度。 给一个主串S以及M个字符串。问这M个字符串在主串中出现多少次。 下面M行,每行一个字符串,定义如题。 下面一行N个字母,即主串S。 Output 一个正整数,表示出现的次数。 Sample Input 10 3 a aba abc abcabababa Sample Output 9 Hint 【数据范围】 对于40%的数据,1<=n<=10000,1<=m<=100 对于100%的数据,1<=n<=2000000,1<=m<=3000,1<=l<=10 保证所有字母都是英文小写字母。 代码   不用指针的忠实党已经痛苦得不想说话。感谢大佬=v= #include

HDU - 2222 Keywords Search AC自动机

不问归期 提交于 2019-11-26 16:58:01
题目链接: https://vjudge.net/problem/HDU-2222 题意:n个字符串在文本串出现的总次数 学习博客: https://blog.csdn.net/bestsort/article/details/82947639 在为下一个节点找fail的时候: 有这个节点,失配后指向父亲失配后指向的那个节点的下一个 没有这个节点,直接指向失配后指向的那个节点 实现方式:bfs #include <bits/stdc++.h> using namespace std; const int N = 5e5 + 10; struct AC { int tree[N][26]; int fail[N]; int val[N]; int tot; void init(int x) { tot = 0; for(int i = 0; i <= x; i++) { fail[i] = 0; val[i] = 0; for(int j = 0; j < 26; j++) tree[i][j] = 0; } } void insert(char *str) { int len = strlen(str); int p = 0, op; for(int i = 0; i < len; i++) { op = str[i] - 'a'; if(tree[p][op] == 0)

[AC自动机][树状数组]luogu P2414 阿狸的打字机

浪子不回头ぞ 提交于 2019-11-26 15:45:37
https://www.luogu.org/problem/P2414 分析 容易发现询问串A属于串B多少次就是问访问串B时,跳完每个点的fail链,到达串A末尾的次数 可以发现如果把fail树建出来,就相当于每到达一个点,就往fail树里面权值+1,离开时-1,当到达串B末尾时,询问串A末尾在fail树中子树的权值和 用DFS序和树状数组可以轻松解决 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> #define lowbit(x) x&-x using namespace std; const int N=2e5+10; struct Graph { int v,nx; }g[N]; int gcnt,list[N]; int fail[N],t[N][26],cnt,v[N]; struct Query { int x,y,id; }q[N]; int m,len,tme,p; int l[N],r[N],end[N],ans[N],f[N]; char c[N]; void Add(int u,int v) { g[++gcnt]=(Graph){v,list[u]};list[u]=gcnt; } bool CMP(Query a

AC自动机

混江龙づ霸主 提交于 2019-11-26 12:07:00
AC自动机模板 #include<bits/stdc++.h> using namespace std; #define maxn 1000005 #define maxm 28 struct AC{ int trieN; int ch[maxn][maxm]; int val[maxn]; int fail[maxn]; void init() { trieN=-1; newnod(); } int newnod() { memset(ch[++trieN],0,sizeof ch[0]); val[trieN]=fail[trieN]=0; return trieN; } void insert(const string & str) { int cur=0; for(int i=0;i<str.size();i++){ int d=str[i]-'a'; if(!ch[cur][d]){ ch[cur][d]=newnod(); } cur=ch[cur][d]; } val[cur]++; } void build() { queue<int> q; for(int i=0;i<maxm;i++){ if(ch[0][i]){ q.push(ch[0][i]); } } while(!q.empty()){ int cur=q.front(); q.pop(); for