Trie图(模板)

Trie图(蒟蒻听说AC自动机能做的题Trie图都能做,而且AC自动机可能被卡,就没学过AC自动机),最近想捡一捡,好久之前做的了。

Trie图,就是一个在Trie树上建的图  大概描述一下

比如说有几个字符串:

abc

abcd

bcd

bacd

jdr

ac

先把它们存在Trie树中:

就像KMP那样,做出这样的逻辑判断:

bacd比较到第三位bac结果没有d,但起码bac有了,所以以bac为前缀的或以bac后缀为前缀的串是不用再比较前缀了。

所以出现了fail指针,为失配情况重新定位方案。

类似于next数组。

无解(定位不到失配后新方案),就指向根表示无解。

显而易见,首字母失配是一定没有方案的。

其次,一个字母失配可以定位到父节点失配的自己值子节点。

一个优化:没有新子节点的节点直接指向fail指针自己值子节点。

建出来Trie图是这样的:

匹配时类似KMP:

模板代码(luogu P3808 【模板】AC自动机(简单版)):

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 struct trnt{
 6     int ch[26];
 7     int val;
 8     int fl;
 9 }tr[1000000];
10 std::queue<int>Q;
11 char tmp[1000003];
12 int siz;
13 int n;
14 void add(char *a)
15 {
16     int len=strlen(a+1);
17     int root=0;
18     for(int i=1;i<=len;i++)
19     {
20         int c=a[i]-‘a‘;
21         if(!tr[root].ch[c])
22             tr[root].ch[c]=++siz;
23         root=tr[root].ch[c];
24     }
25     tr[root].val++;
26 }
27 void Build()
28 {
29     int root=0;
30     for(int i=0;i<26;i++)
31         if(tr[root].ch[i])
32             Q.push(tr[root].ch[i]);
33     while(!Q.empty())
34     {
35         root=Q.front();
36         Q.pop();
37         for(int i=0;i<26;i++)
38         {
39             if(tr[root].ch[i])
40             {
41                 tr[tr[root].ch[i]].fl=tr[tr[root].fl].ch[i];
42                 Q.push(tr[root].ch[i]);
43             }else
44                 tr[root].ch[i]=tr[tr[root].fl].ch[i];
45         }
46     }
47     return ;
48 }
49 int Cal(char *a)
50 {
51     int len=strlen(a+1);
52     int ans=0;
53     int root=0;
54     for(int i=1;i<=len;i++)
55     {
56         int c=a[i]-‘a‘;
57         root=tr[root].ch[c];
58         for(int j=root;j&&(tr[j].val!=-1);j=tr[j].fl)
59         {
60             ans+=tr[j].val;
61             tr[j].val=-1;
62         }
63     }
64     return ans;
65 }
66 int main()
67 {
68     scanf("%d",&n);
69     for(int i=1;i<=n;i++)
70     {
71         scanf("%s",tmp+1);
72         add(tmp);
73     }
74     Build();
75     scanf("%s",tmp+1);
76     printf("%d\n",Cal(tmp));
77     return 0;
78 }

原文地址:https://www.cnblogs.com/blog-Dr-J/p/9670219.html

时间: 2024-08-30 15:44:28

Trie图(模板)的相关文章

hihoCoder #1036 : Trie图 (AC自动机)

#1036 : Trie图 时间限制:20000ms 单点时限:1000ms 内存限制:512MB 描述 前情回顾 上回说到,小Hi和小Ho接受到了河蟹先生伟大而光荣的任务:河蟹先生将要给与他们一篇从互联网上收集来的文章,和一本厚厚的河蟹词典,而他们要做的是判断这篇文章中是否存在那些属于河蟹词典中的词语. 当时,小Hi和小Ho的水平还是十分有限,他们只能够想到:"枚举每一个单词,然后枚举文章中可能的起始位置,然后进行匹配,看能否成功."这样非常朴素的想法,但是这样的算法时间复杂度是相当

模板—trie图

做了某题之后发现trie的AC自动机太垃圾了,动不动就TLE,然后我就去学了trie图. #include<iostream> #include<cstdio> using namespace std; struct trie { int count; trie *fail,*nxt[26]; trie() { count=0; fail=NULL; for(int i=0;i<26;i++)nxt[i]=NULL; } }*q[1000000],*root=new trie

Trie图

DFA 确定性有限状态自动机 DFA确定性有限状态自动机是一种图结构的数据结构,可以由(Q, q0, A, Sigma, Delta)来描述,其中Q为状态集,q0为初始状态,A为终态集合,Sigma为字母表,Delta为转移函数.它表示从唯一一个起始状态q0开始,经过有限步的Delta转移,转移是根据字母表Sigma中的元素来进行,最终到达终态集合A中的某个状态的状态移动.  如图所示是一个终态集合为{"nano"}的DFA.     DFA只能有一个起点而可以有多个终点.每个节点都有

Trie图/AC自动机

made...发财谷题解基本是Trie图... 我永远喜欢AC自动机.jpg 下面是P3808 [模板]AC自动机(简单版) 的两种写法 Trie图 const int MAXN = 1000010; int t[MAXN][26], word[MAXN], fail[MAXN], cnt, q[MAXN]; inline void insert(char *s) { int u = 0; for (int i = 1; s[i]; ++i) { int v = s[i] - 'a'; int

DNA Sequence POJ - 2778 邻接矩阵 trie图 矩阵快速幂

首先构造trie图. 我们明确一点的是,给出trie图,那么所有点的转移方式都是唯一可以确定的.即使是没有这个字符,他也会指向根节点. 我们根据离散数学的知识可以知道.计算有向图的邻接矩阵,然后k次方,就能够计算出从某一个点到另一个点,有多少条长度为k的路径. 故,我们构造出来trie图,拿出该图的邻接矩阵,就能计算路径数目.--(注意改图是有向图)-- trie图的构造不说了,模板. 邻接矩阵的构造根据trie图来的.我们在trie图上找到每一个节点,查看他的相邻节点,即A,G,C,T四个点指

poj3630 Phone List (trie树模板题)

Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26328   Accepted: 7938 Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogu

HDU 1251 Trie树模板题

1.HDU 1251 统计难题  Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b #define F(i,a,b

hiho一下 第二周&amp;第四周:从Trie树到Trie图

hihocoder #1014 题目地址:http://hihocoder.com/problemset/problem/1014 hihocoder #1036 题目地址: http://hihocoder.com/problemset/problem/1036 trie图其实就是trie树+KMP #1014trie树 #include<stdio.h> #include <algorithm> #include <cstring> #include <str

Trie图 &amp; AC自动机初学(1)

题目来源于:Hihocoder 时间限制:20000ms 单点时限:1000ms 内存限制:512MB 描述 前情回顾 上回说到,小Hi和小Ho接受到了河蟹先生伟大而光荣的任务:河蟹先生将要给与他们一篇从互联网上收集来的文章,和一本厚厚的河蟹词典,而他们要做的是判断这篇文章中是否存在那些属于河蟹词典中的词语. 当时,小Hi和小Ho的水平还是十分有限,他们只能够想到:"枚举每一个单词,然后枚举文章中可能的起始位置,然后进行匹配,看能否成功."这样非常朴素的想法,但是这样的算法时间复杂度是