[hiho 04]Trie图

题目描述

Trie 图就是在 Trie 树上建立 fail 指针,类似于KMP算法中的next数组的作用。

这个数据结构的作用是判断一个字符串中是否包含一组字符串中的任意一个。

结构体定义是这样的:

typedef
struct trie_node {
	trie_node *nodes[26];
	trie_node *fail = NULL;
	bool word_end = false;
	trie_node() {
		for (int i = 0; i < 26; i++) {
			nodes[i] = NULL;
		}
	}
} Trie, *PTrie;

与KMP类似,fail的定义如下:

记S[pnode]为从proot到pnode构成的字符串,所有满足S[i]是S[node]后缀串的节点i构成集合M,pnode->fail是集合M中使得S[pnode->fail]字符串长度最长的节点。

定义起来很拗口,但是如果理解KMP算法的话,fail和next的定义几乎一样。

求法也是相似的,用父节点的fail指针迭代求解。由于要利用父节点的信息,所以用层次遍历(bfs)的方法求解Trie树上每个节点的fail。

void trie_map(PTrie proot) {
	queue<PTrie> q;
	proot->fail = NULL;
	q.push(proot);
	while (!q.empty()) {
		PTrie pnode = q.front();q.pop();
		PTrie pfail;

		for (int i = 0; i < 26; i++) {
			if (pnode->nodes[i] != NULL) {
				q.push(pnode->nodes[i]);
				pfail = pnode->fail;
				while (pfail != NULL) {
					if (pfail->nodes[i]) break;
					else pfail = pfail->fail;
				}
				pnode->nodes[i]->fail = pfail == NULL ? proot : pfail->nodes[i];
			}
		}
	}
}

hexie词匹配就是在树上不断匹配当前字符,遇到不匹配就转到fail节点继续匹配当前字符,一旦途中走到了一个单词结尾的节点就返回1,若匹配完整个字符串还没有返回,说明没有匹配到hexie词,返回0。

bool hexie(PTrie proot, char *str) {
	PTrie pcur = proot;
	int str_len = strlen(str);
	for (int i = 0; i < str_len; i++) {
		int pos = str[i] - ‘a‘;
		if (pcur->nodes[pos] != NULL) {
			pcur = pcur->nodes[pos];
		}
		else {
			pcur = pcur->fail;
			if (pcur == NULL) {
				pcur = proot;
				continue;
			}
			i--;
		}
		if (pcur->word_end) return true;
	}
	return false;
}

总而言之,Trie图跟KMP很像。可以说KMP是Trie图的特例、KMP是Trie树退化成链表后构成的Trie图。理解了KMP与Trie树,Trie图应该不在话下。

时间: 2024-12-07 00:33:22

[hiho 04]Trie图的相关文章

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的水平还是十分有限,他们只能够想到:"枚举每一个单词,然后枚举文章中可能的起始位置,然后进行匹配,看能否成功."这样非常朴素的想法,但是这样的算法时间复杂度是

hihocoder 1036 Trie图(AC自动机)

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

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

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

Trie 图

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

Trie图

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

hihoCoder#1036 Trie图

原题地址 看了这篇博文,总算是把Trie图弄明白了 Runtime Error了无数次,一直不知道为什么,于是写了个脚本生成了一组大数据,发现果然段错误了. 调试了一下午,总算闹明白了,为什么呢? 1. 空间超大的变量不要放在函数里,会爆栈,应该弄成全局变量或者是从堆上动态分配. 2. 看清题目的数据范围,一开始我的MAX_NODE设的是1024... 代码: 1 #include <iostream> 2 #include <cstring> 3 4 using namespac

hdu2457 Trie图+dp

hdu2457 给定n个模式串, 和一个文本串 问如果修改最少的字符串使得文本串不包含模式串, 输出最少的次数,如果不能修改成功,则输出-1 dp[i][j] 表示长度为i的字符串, 到达状态j(Trie图中的结点)所需要修改的最少次数 那么dp[0->n][0->size] = INF ,  dp[0][root] = 0,  n代表字符串长度, size代表状态数 那么答案就是  min{dp[n][size]} 我们根据模式串所建的Trie图, 进行模拟构造不包含模式串的字符串 从第一个

【hihoCoder】1036 Trie图

题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中的单词words. 相关基础的理解 1. 与用KMP解决的问题的差别 KMP:输入原串S和一个模式串T,判断T是否出现在S中.通过对T计算next数组,避免原串S的回溯. 现在的问题:输入文本串text和多个单词words,判断words中是否有出现在text中.同样希望输入的text不用进行回溯.