字符串匹配相关模板(字典树、KMP、AC自动机)

字典树

struct Trie
{
	int ch[MAXN][26];
	int cnt;
	Trie()
	{
		cnt=1;
		memset(ch[0],0,sizeof(ch[0]));
	}

	int idx(char c)
	{
		return c-‘a‘;
	}

	void insert(char *s,int v)
	{
		int u=0,len=strlen(s);
		for (int i=0;i<len;i++)
		{
			int c=idx(s[i]);
			if (!ch[u][c])
			{
				memset(ch[cnt],0,sizeof(ch[cnt]));
				ch[u][c]=cnt++;
			}
			u=ch[u][c];
		}
		val[u]=v;
	}
} tree;

AC自动机

struct ACauto
{
	int ch[MAXN][26];
	int cnt;
	int f[MAXN],last[MAXN],val[MAXN];

	Trie()
	{
		cnt=1;
		memset(ch[0],0,sizeof(ch[0]));
	}

	int idx(char c)
	{
		return c-‘a‘;
	}

	void insert(char *s,int v)
	{
		int u=0,len=strlen(s);
		for (int i=0;i<len;i++)
		{
			int c=idx(s[i]);
			if (!ch[u][c])
			{
				memset(ch[cnt],0,sizeof(ch[cnt]));
				ch[u][c]=cnt++;
			}
			u=ch[u][c];
		}
		val[u]=v;
	}

	void print(int j)
	{
		if (j)
		{
			printf("%d: %d\n",j,val[j]);
			print(last[j]);
		}
	}

	int getFail()
	{
		queue <int> q;
		f[0]=0;
		for (int c=0;c<26;c++)
		{
			int u=ch[0][c];
			if (u)
			{
				f[u]=0;
				q.push(u);
				last[u]=0;
			}
		}

		while (!q.empty())
		{
			int r=q.front(); q.pop();
			for (int c=0;c<26;c++)
			{
				int u=ch[r][c];
				if (!u)
				{
					ch[r][c]=ch[f[r]][c];
					continue;
				}
				q.push(u);
				int v=f[r];
				f[u]=ch[v][c];
				last[u]=val[f[u]]?f[u]:last[f[u]];
			}
		}
	}

	void find(char *T)
	{
		int n=strlen(T);
		int j=0;
		for (int i=0;i<n;i++)
		{
			int c=idx(T[i]);
			while(j&&!ch[j][c]) j=f[j];
			j=ch[j][c];
			if (val[j]) print(j);
			else if (last[j]) print(last[j]);
		}
	}
} tree;

  

时间: 2024-10-24 12:29:16

字符串匹配相关模板(字典树、KMP、AC自动机)的相关文章

HDU 5384 字典树、AC自动机

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5384 用字典树.AC自动机两种做法都可以做 1 #include<stdio.h> 2 #include<string.h> 3 #include<string> 4 #include<iostream> 5 using namespace std; 6 struct node{ 7 int cnt; 8 node *next[26]; 9 node(){ 10 c

LA_3942 LA_4670 从字典树到AC自动机

首先看第一题,一道DP+字典树的题目,具体中文题意和题解见训练指南209页. 初看这题模型还很难想,看过蓝书提示之后发现,这实际上是一个标准DP题目:通过数组来储存后缀节点的出现次数.也就是用一颗字典树从后往前搜一发.最开始觉得这种搞法怕不是要炸时间,当时算成了O(N*N)毕竟1e5的数据不搞直接上N*N的大暴力...后来发现,字典树根本跑不完N因为题目限制字典树最多右100层左右. 实际上这道题旧思想和模型来说很好(因为直观地想半天还真想不出来..)但是实际实现起来很简单--撸一发字典树就好了

hdu-(1298手机相关 dfs+字典树)

题目大意: 在以前,手机输入法很麻烦,因为只有9个键,而字母有26个,所以一个键上同时包含这几个字母,这样的话,为了打出一个字母可能要按几次.比如键5有"JKL", 如果要输入K,那么就要连按两次. 这样的输入法很麻烦.所以一家公司发明了T9技术输入法.这种输入法内置这很多英语单词,它可以根据英语出现的频率,是否存在等信息,每个字母只要按一次,就可以有想要的预选单词. 例如,假设输入法只内置了一个单词"hell", 那么只需要按4355便可以出来. 注意,如果有一个

[知识点]Trie树和AC自动机

// 此博文为迁移而来,写于2015年5月27日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w1s8.html 1.前言 怪我咯,因为Trie树和AC自动机的密切相关,我想一起讲完哈哈...看过前面博文的同学应该都知道了,AC自动机其实就是相当于在Trie树上跑KMP. 2.Trie树 Trie树,就是字母树.Trie树是多叉树,每个节点为一个字母.其根节点为象征节点(就是说没有含义,但是存在这个节点),从根节点开

优先队列 + 并查集 + 字典树 + 树状数组 + 线段树 + 线段树点更新 + KMP +AC自动机 + 扫描线

这里给出基本思想和实现代码 . 优先队列 : 曾经做过的一道例题       坦克大战 1 struct node 2 { 3 int x,y,step; 4 friend bool operator <(node s1,node s2) // 定义结构体 的时候 这个 就是 用于 优先队列的 基准排序 5 { 6 return s1.step>s2.step; // 步数小的 在上 为小顶堆 7 } 8 }; 9 priority_queue<node>Q; // 优先队列的结构

模板——字典树Trie Tree

/*字典序模板*/ #define MAX 26 //每层有多少种类 typedef struct trie { trie *next[MAX]; int v;//一个字典树到此有多少相同前缀的数目 }; trie *root; void creat_trie(char *str) { int len=strlen(str); trie *p=root,*q; for(int i=0;i<len;i++) { int id=str[i]-'a'; if(p->next[id]==NULL) {

中文分词系列(二) 基于双数组Tire树的AC自动机

秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自动机,要学会AC自动机,我们必须知道什么是Trie,也就是字典树.Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.之

woj1572 Cyy and Fzz KMP / AC自动机 + DP

题目:http://acm.whu.edu.cn/land/problem/detail?problem_id=1572 题意:  有n个目标串,长度均小于15,(n<=8),现在随机写一个长度为L的字符串,问写下的这个字符串包含目标串的期望的个数. 比赛的时候还以为是水题,其实是自己太水.这种题一般是AC自动机的中等题,本题也可以用KMP做,结合状压dp. 方法一:AC自动机 建完Trie树后,就是跑一遍dp,注意单词节点要 |=(1<<val),会有重的字符串. dp过程: 用 dp

【uva1502/hdu4117-GRE Words】DP+线段树优化+AC自动机

这题我的代码在hdu上AC,在uva上WA. 题意:按顺序输入n个串以及它的权值di,要求在其中选取一些串,前一个必须是后一个的子串.问d值的和最大是多少. (1≤n≤2×10^4 ,串的总长度<=3*10^5) 题解: 这题一开始我的方向就错了,想了很久d[x][y]表示在AC自动机上的节点x.下一个串要大于y的dp.然而这样做数组要10^4*10^5=10^9级别,开都开不了,妥妥超时. 后来看了一眼题解...觉得自己智商真是感人... 用f[i]表示以第i个串为结尾的时候最大的d值,这样做