ac自动机

AC自动机

匿名 (未验证) 提交于 2019-12-02 21:53:52
1.根据字符构造trie树 2.构建失败匹配指针 1.根节点的所以一代子孩子失败指针都指向root 2.子节点匹配失败时,找到父节点的失败指针,找不到就一直找,直到找到root还匹配不到,直接指向root 3.文本串匹配 1.如果已经匹配到完整的模式串,根据失败指针切换线路继续向下查找 2.如果还没有匹配完,那么就向下匹配 class ACNode { constructor(data){ this.data = data this.children = new Map() this.isEndingChar = false this.length = 0 this.fail = null } } class ACTree { constructor(){ this.root = new ACNode('/') } insert(text){ let node = this.root for(let char of text){ if(!node.children.get(char)){ node.children.set(char,new ACNode(char)) } node = node.children.get(char) } node.isEndingChar = true node.length = text.length } buildFailurePointer(

P2444 [POI2000]病毒 AC自动机

被刻印的时光 ゝ 提交于 2019-12-02 19:15:52
P2444 [POI2000]病毒 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 35000; 4 5 struct Aho_Corasock_Automaton { 6 struct node { 7 int fail; // 失配指针 8 int son[2]; // 子节点的位置 9 bool danger; // 危险标记 10 }Trie[maxn]; 11 int cnt = 0; // Trie指针 12 void insert(char *s) { 13 int len = strlen(s); 14 int now = 0; // Trie当前指针 15 for (int i = 0; i < len; ++i) { 16 if (Trie[now].son[s[i]-'0'] == 0) { // 如果没有这个子节点 17 Trie[now].son[s[i]-'0'] = ++cnt; // 构造该节点 18 } 19 now = Trie[now].son[s[i]-'0']; 20 } 21 Trie[now].danger = true; 22 } 23 void get_fail() { // 构造fail指针 24 queue<int> que; 25 for

P2444 [POI2000]病毒------ac自动机+dfs

梦想与她 提交于 2019-12-02 15:01:34
原题 这里有个技巧,就是关于怎么找到无限长的字符串,其实就是在ac机上寻找环,这个环中不允许有任何模板字符串的fail指针指着环的人任何一节。 所以用pos存是否该字符串存在模板字符串的,如果pos[fail[x]]是1,那么pos[x]必是1,因为在fail树中,父树永远出现在子树中,而且是后缀。 # include <bits/stdc++.h> using namespace std ; const int MX = 1e5 + 9 ; int n , tot = 0 , pos [ MX ] , t [ MX << 2 ] [ 2 ] , fail [ MX ] ; char s [ MX ] ; void inst ( ) { int now = 0 ; for ( int i = 0 ; s [ i ] ; i ++ ) { int a = s [ i ] - '0' ; if ( ! t [ now ] [ a ] ) t [ now ] [ a ] = ++ tot ; now = t [ now ] [ a ] ; } pos [ now ] = 1 ; } void build ( ) { queue < int > que ; for ( int i = 0 ; i <= 1 ; i ++ ) if ( t [ 0 ] [ i ] ) que . push (

hdu5880 ac自动机模板

旧巷老猫 提交于 2019-12-02 02:45:09
ac自动机: 给你若干个单词,判断一段文字里边这些单词出现了吗,在哪出现,出现几次? 首先是字典树模板: #include<bits/stdc++.h> #define debug printf("!"); using namespace std; const int maxn=1e3+50; struct trie_node{ int count; trie_node*son[26]; }; trie_node* new_node() { trie_node* pnode=new trie_node(); pnode->count=0; for(int i=0;i<26;i++)pnode->son[i]=NULL; return pnode; } void trie_insert(trie_node *root,char key[]) { trie_node* node=root; char *p=key; while(*p) { if(node->son[*p-'a']==NULL)node->son[*p-'a']=new_node(); node=node->son[*p-'a']; ++p; } node->count+=1; } int trie_search(trie_node *root,char key[]) { trie_node*node=root;

牛客 单词 ac自动机

故事扮演 提交于 2019-12-01 10:20:20
题目链接: https://ac.nowcoder.com/acm/problem/20443 思路:这道题给出了很多的单词,现在问每一个单词在所有单词中出现的总次数。步骤就是先建一棵字典树,再构建fail指针,最后把整棵字典树的节点遍历一遍。   我们可以在建字典树的时候可以先把每个节点经过的次数先算出来,因为字典树上的每一个节点都代表一个不同的字符串(从根节点到这个节点的路径唯一),所以我们字典树上每一个节点一开始计算出来的经过的次数就是 这个节点所代表的字符串 作为所有输入单词 前缀 的次数。   例如我们有单词aa,aab,aba,那么假设字典树上从根节点到某一个节点u构成的字符串是aa,那么我们在建字典树时,经过点u的次数就是2,因为aa在这些单词中作为前缀出现的次数就是2( aa , aa b,aba)。   然后我们再构建fail指针,fail[u]其实就代表从根节点到fail[u]构成的这个 前缀 和以节点u结尾的长度相同的 后缀 是一样的,而我们已经把字符串作为前缀出现的次数算出来了,我们只要将每一个前缀在整棵树上作为其他串后缀的次数计算出来,那么这个字符串出现的总次数也就是两个次数相加。而这个总次数我们可以依靠fail指针来线性求出,在我们构建fail指针的时候,我们肯定是先遍历到每一个前缀,所以这个前缀肯定会先出现在队列中,在队列中的位置会排在 其他字符串 -

Kattis - nvwls (AC自动机last优化 + dp)

孤者浪人 提交于 2019-12-01 07:52:40
题意 给出一个字典,每个单词去掉元音字母 A、E、I、O、U 之后形成一个新字典。 先给出一个只有辅音组成的串,用原字典中的单词还原该串,若存在多种还原方式,输出还原后元音字母数量最多的那种,若依旧多种,则任意输出。 传送门 思路 ac自动机fail树上跑dp的一眼套路题。 总结一下遇到的坑: 多个单词去掉元音字母之后形成的新单词相同。 若原单词只有辅音字母。 dp过程中未保证完全还原辅音串。 特殊样例将 跳fail的过程卡成了 \(n^2\) 。 解决办法: 在字典树的结尾节点保存编号时,保存最大值。 将初值从 $0 $ 改为 \(-1\) 。 dp数组初值同样改为 \(-1\) , \(dp[0] = 0\) ,dp只能由非 \(-1\) 的状态转移。 对fail数组进行 last优化 。 last[u] = len[fail[u]]? fail[u]: last[fail[u]]; 。 last优化 普通方法将建图+匹配的复杂度成功优化为了 𝑂(∑𝑛+𝑚) ,但是,匹配成功时的计数也是需要跳fail边的。然而,为了跳到一个结束节点,我们可能需要中途跳到很多没用的伪结束节点: 如果一个节点的fail指向一个结尾节点,那么这个点也成为一个(伪)结尾节点。在匹配时,如果遇到结尾节点,就进行相应的计数处理。 这里面就又有优化的余地了:对于不是真正结束节点的伪结束点,直接跳过它就好了

hdu 4758 (AC自动机)

非 Y 不嫁゛ 提交于 2019-12-01 06:21:57
除了走到哪里,还要加状态表示当前节点和已经匹配的串 #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define lson l,m,rt<<1 #define pi acos(-1) #define rson m+1,r,rt<<1|1 #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define eps 1e-8 using namespace std; const int maxn = 250,maxs = 5; const ll inf = 1e9; const ll mod = 1000000007; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<

hdu 4511 (AC自动机)

你。 提交于 2019-12-01 06:12:50
注意标记一个点后,fail树上的子节点都会被标记 跑spfa,dp也可以 #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define lson l,m,rt<<1 #define pi acos(-1) #define rson m+1,r,rt<<1|1 #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define eps 1e-8 using namespace std; const int maxn = 50050; const ll inf = 1e9; const ll mod = 998244353; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&

HDU - 2457-DNA repair(AC自动机, DP)

社会主义新天地 提交于 2019-12-01 02:12:22
链接: https://vjudge.net/problem/HDU-2457 题意: Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a DNA is represented as a string containing characters 'A', 'G' , 'C' and 'T'. The repairing techniques are simply to change some characters to eliminate all segments causing diseases. For example, we can repair a DNA "AAGCAG" to "AGGCAC" to eliminate the initial causing disease segments "AAG", "AGC" and "CAG" by changing two characters. Note that the repaired DNA can still contain only characters 'A', 'G', 'C'

HDU-2296-Ring(AC自动机, DP)

拥有回忆 提交于 2019-11-30 21:43:23
链接: https://vjudge.net/problem/HDU-2296 题意: For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic string engraved on. The string's length should not exceed N. The careful Steven knows Jane so deeply that he knows her favorite words, such as "love", "forever". Also, he knows the value of each word. The higher value a word has the more joy Jane will get when see it. The weight of a word is defined as its appeared times in the romantic string multiply by its value, while the weight of the romantic string is defined as the sum of all words' weight. You should