[HIHO1036] Trie图(AC自动机)

题目链接:http://hihocoder.com/problemset/problem/1036

不知道为什么匹配到某点存在next[idx]的时候,只需要检查这一个sign就行,如果检查此点的fail的sign就会TLE。

大概数据比较弱能让我水过吧。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 typedef struct Node {
 5     Node* fail;
 6     Node* next[26];
 7     bool sign;
 8     Node() { fail = NULL; for(int i = 0; i < 26; i++) next[i] = NULL; }
 9 }Node;
10
11 const int maxn = 1000100;
12 Node* rt;
13 int n;
14 char tmp[maxn];
15
16 void insert(Node* rt, char* str) {
17     Node* tmp = rt;
18     for(int i = 0; str[i]; i++) {
19         int idx = str[i] - ‘a‘;
20         if(tmp->next[idx] == NULL) tmp->next[idx] = new Node();
21         tmp = tmp->next[idx];
22     }
23     tmp->sign = 1;
24 }
25
26 void build(Node* rt) {
27     Node* cur;
28     Node* tmp;
29     queue<Node*> q;
30     q.push(rt);
31     while(!q.empty()) {
32         cur = q.front(); q.pop();
33         for(int i = 0; i < 26; i++) {
34             if(!cur->next[i]) continue;
35             if(cur == rt) cur->next[i]->fail = rt;
36             else {
37                 tmp = cur->fail;
38                 do {
39                     if(tmp->next[i]) {
40                         cur->next[i]->fail = tmp->next[i];
41                         break;
42                     }
43                 } while(tmp = tmp->fail);
44                 if(tmp == NULL) cur->next[i]->fail = rt;
45             }
46             q.push(cur->next[i]);
47         }
48     }
49 }
50
51 bool query(Node* rt, char* str) {
52     Node* cur = rt;
53     for(int i = 0; str[i]; i++) {
54         int idx = str[i] - ‘a‘;
55         while(cur->next[idx] == NULL && cur != rt) cur = cur->fail;
56         cur = cur->next[idx];
57         if(cur == NULL) {
58             cur = rt;
59             continue;
60         }
61         if(cur->sign) return 1;
62     }
63     return 0;
64 }
65
66 int main() {
67     // freopen("in", "r", stdin);
68     while(~scanf("%d", &n)) {
69         rt = new Node();
70         for(int i = 0; i < n; i++) {
71             scanf("%s", tmp);
72             insert(rt, tmp);
73         }
74         build(rt);
75         scanf("%s", tmp);
76         if(query(rt, tmp)) puts("YES");
77         else puts("NO");
78     }
79     return 0;
80 }
时间: 2024-11-10 06:16:27

[HIHO1036] Trie图(AC自动机)的相关文章

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

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

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

结合双数组Trie的AC自动机算法

结合双数组Trie的AC自动机算法是一种相对比较快的词匹配算法,常见于分词系统用于分词,本文准备用伪代码结合实例的形式来讲解一下该匹配算法的实现原理 构建步骤: 1.Trie树的构建 首先直观感受一下Trie树: 插入模式串 ball.bat.doll.dork.dorm.do.send.sense之后形成的trie树 trie树分三步:插入(构建).查找.删除 插入: 1.输入一个模式串 String 2.如果该模式串已经存在于树中,则跳转 8.如果不存在,跳转3 3.设置当前节点为根节点 4

HDU-1251 统计难题(Trie、AC自动机)

统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submission(s): 44119    Accepted Submission(s): 15817 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的

模板—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

AC自动机详解

首先,看清楚了,这是AC自动机不是自动AC机 引用AC自动机模板题上的一句话: ovo 在学习AC自动机之前,应该先掌握一下两个前置技能: Trie KMP AC自动机,通俗地讲,就是在Trie上跑KMP.AC自动机利用Trie的性质和KMP的思想,可以实现字符串的多模匹配.KMP是单模匹配,而它与AC自动机最大的区别就在fail指针的求法,其余思想基本相同. 所谓多模匹配,即给出若干个模式串和一个文本串,需要查找这些模式串在文本串中出现的情况. AC自动机的操作分为三步: 建树 求fail指针

视频游戏的连击 [USACO12JAN](AC自动机+动态规划)

传送门 默认大家都学过trie与AC自动机. 先求出fail,对于每个节点维护一个sum,sum[u]待表从根到u所形成的字符串能拿到几分.显然sum[u]=sum[fail] + (u是几个字符串的结尾). 设dp[i][j]代表长度为i到trie树上的j号节点所得的最大分数,显然有dp[i+1][j的字符k儿子] = max{dp[i+1][j的字符k儿子], dp[i][j] + sum[j的字符k儿子]} memset(dp, -1, sizeof(dp)); dp[0][1] = 0;

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

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

hihocoder 1036 Trie图(AC自动机)

传送门 Description 上回说到,小Hi和小Ho接受到了河蟹先生伟大而光荣的任务:河蟹先生将要给与他们一篇从互联网上收集来的文章,和一本厚厚的河蟹词典,而他们要做的是判断这篇文章中是否存在那些属于河蟹词典中的词语. 当时,小Hi和小Ho的水平还是十分有限,他们只能够想到:“枚举每一个单词,然后枚举文章中可能的起始位置,然后进行匹配,看能否成功.”这样非常朴素的想法,但是这样的算法时间复杂度是相当高的,如果说词典的词语数量为N,每个词语长度为L,文章的长度为M,那么需要进行的计算次数是在N