vijos-1951 玄武密码

题意:

给出一个匹配串和n个单词;

求每个单词在匹配串中出现的的最大前缀长度;

匹配串长度<=10^7,n<=10^5,单词长度<=100;

题解:

当年啥也不会天真的一发KMP骗掉了50分,然后看题解说是自动机感觉好神啊;

现在回来复习自动机就把这道题切了试试;

基本的建立自动机什么的不说了;

主要就是答案的处理上我是在trie树上记录一个is的数组;

然后每个和匹配串匹配到了的结点全都标记上;

(当然这里要把fail指针的一连串的后缀相同的结点标记)

最后和建树时一样扫一遍自动机,每个单词标记的最大前缀长度就是答案;

建树和找答案的复杂度是O(100n),自动机匹配大概是O(10^7)左右咯;

有个小优化,找后缀时发现已经标记的就可以退出了,因为后面一定也被标记完成了;

大概可以省500ms;

还有一点。。。因为匹配串很长字符集很少单词很短;

所以大随机数据可以视为单词全在匹配串中从而可能骗掉4个点233333(orz gaoj,思路太神);

代码:

#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100001
#define M 10000001
using namespace std;
queue<int>q;
int fail[M], next[M][4], root, tot = 1;
char str[M], a[N][101];
bool is[M];
int f(char a)
{
	switch (a)
	{
		case 'E':	return 0;
		case 'S':	return 1;
		case 'W':	return 2;
		case 'N':	return 3;
	}
}
void insert(char *s)
{
	int p=root,index;
	while (*s != '\0')
	{
		index = f(*s);
		if (next[p][index] == 0)
			next[p][index] = ++tot;
		p=next[p][index];
		s++;
	}
}
void Build()
{
	int p, temp, i;
	q.push(root);
	while (!q.empty())
	{
		p = q.front(), q.pop();
		for (i = 0; i < 4; i++)
		{
			if (next[p][i])
			{
				temp = fail[p];
				while (temp)
				{
					if (next[temp][i])
					{
						fail[next[p][i]] = next[temp][i];
						break;
					}
					temp = fail[temp];
				}
				if (!temp)	fail[next[p][i]] = root;
				q.push(next[p][i]);
			}
		}
	}
}
void query(char *s)
{
	int index, p, temp;
	p = root;
	while (*s != '\0')
	{
		index = f(*s);
		while (next[p][index] == 0 && p)
			p = fail[p];
		p = p ? next[p][index] : root;
		temp = p;
		while (temp&&is[temp] == 0)
		{
			is[temp] = 1;
			temp = fail[temp];
		}
		s++;
	}
}
void slove(char *s)
{
	int p = root, index, ret = 0;
	while (*s != '\0')
	{
		index = f(*s);
		if (is[next[p][index]])
			ret++;
		else
			break;
		p = next[p][index];
		s++;
	}
	printf("%d\n", ret);
}
int main()
{
	int n, m, i, j, k, len;
	scanf("%d%d", &len, &n);
	scanf("%s", str);
	for (i = root = 1; i <= n; i++)
	{
		scanf("%s", a[i]);
		insert(a[i]);
	}
	Build();
	query(str);
	for (i = 1; i <= n; i++)
	{
		slove(a[i]);
	}
	return 0;
}
时间: 2024-07-28 20:39:59

vijos-1951 玄武密码的相关文章

【bzoj4327】JSOI2012 玄武密码 AC自动机

题目描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在进香河地区发现了带有玄武密码的文字.更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联.于是,漫长的破译工作开始了. 经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素分别是‘E’,‘S’,‘W’,‘N’,代表了东南西北四

AC自动机 --- [JSOI2012]玄武密码

bzoj 4327 [JSOI2012]玄武密码 题目描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河. 相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在进香河地区发现了带有玄武密码的文字. 更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联.于是,漫长的破译工作开始了. 经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素

【AC自动机】bzoj4327: JSOI2012 玄武密码

题目思路没话讲:主要是做题时候的细节和经验 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在进香河地区发现了带有玄武密码的文字.更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联.于是,漫长的破译工作开始了. 经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的

玄武密码(bzoj4327)(JSOI2012)

题目描述 原题来自:JSOI 2012 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在进香河地区发现了带有玄武密码的文字.更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联.于是,漫长的破译工作开始了. 经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为 NNN 的序列来描述,序列中的元素分别是 E,S,

【AC自动机】玄武密码

[题目链接] https://loj.ac/problem/10058 [题意] 对于每一段文字,其前缀在母串上的最大匹配长度是多少呢 [参考别人的题解] https://www.luogu.org/problemnew/solution/P5231 我们只需要先建立所有密码的trie树再以母串为主串跑一个AC自动机不过其中还是有一些需要改动的地方原本字典树中用来记录某个节点是不是字符串结尾的数组不需要,直接删去我们需要另一个数组来标记哪些点被匹配跑完ac自动机后从trie树上找最后一个匹配的点

TZOJ 5986 玄武密码(AC自动机)

描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在进香河地区发现了带有玄武密码的文字.更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联.于是,漫长的破译工作开始了. 经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素分别是‘E’,‘S’,‘W’,‘N’,代表了东南西北四向,

「JSOI2012」玄武密码

「JSOI2012」玄武密码 传送门 题目是要求多个串在母串上的最长匹配长度. 考虑 \(\text{AC}\) 自动机,我们建出 \(\text{Trie}\) 图然后用母串来在上面跑. 每一个能匹配的位置,它 \(\text{fail}\) 的位置也一定可以匹配,我们就跳 \(\text{fail}\) 把经过的节点的值赋为 \(1\) ,表示这个位置可以匹配. 然后我们每一个模式串,找到ta在 \(\text{Trie}\) 树上最深的可以匹配的节点来计算答案即可. 参考代码: #incl

Vijos P1028 魔族密码(Trie解法)

描述 风之子刚走进他的考场,就--花花:当当当当~~偶是魅力女皇--花花!!^^(华丽出场,礼炮,鲜花)风之子:我呕--(杀死人的眼神)快说题目!否则---_-###花花:--咦~~好冷~~我们现在要解决的是魔族的密码问题(自我陶醉:搞不好魔族里面还会有人用密码给我和菜虫写情书咧,哦活活,当然是给我的比较多拉*^_^*).魔族现在使用一种新型的密码系统.每一个密码都是一个给定的仅包含小写字母的英文单词表,每个单词至少包含1个字母,至多75个字母.如果在一个由一个词或多个词组成的表中,除了最后一个

【动态规划】【二分】【最长上升子序列】Vijos P1028 魔族密码

题目链接: https://vijos.org/p/1028 题目大意: 给N个字符串(N<=2000),求能组成词链的单词最多有几个. 如果在一个由一个词或多个词组成的表中,除了最后一个以外,每个单词都被其后的一个单词所包含 即前一个单词是后一个单词的前缀,则称词表为一个词链.例如下面单词组成了一个词链: i int integer 但下面的单词不组成词链: integer intern 题目思路: [动态规划][二分][最长上升子序列] 二分查找最长可达的长度. 1 // 2 //by co

[vijos p1028] 魔族密码

描述 风之子刚走进他的考场,就……花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花)风之子:我呕……(杀死人的眼神)快说题目!否则……-_-###花花:……咦~~好冷~~我们现在要解决的是魔族的密码问题(自我陶醉:搞不好魔族里面还会有人用密码给我和菜虫写情书咧,哦活活,当然是给我的比较多拉*^_^*).魔族现在使用一种新型的密码系统.每一个密码都是一个给定的仅包含小写字母的英文单词表,每个单词至少包含1个字母,至多75个字母.如果在一个由一个词或多个词组成的表中,除了最后一个