vijos-1951 玄武密码

原创 2015年07月07日 11:35:14

题意:

给出一个匹配串和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;
}


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

Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此...

【JSOI2012】【BZOJ4327】玄武密码

Description在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此。 ...

BZOJ4327 玄武密码 (AC自动机)

题目大意给出一个母串和一些特征串,询问字串能在母串中匹配的最长的前缀的长度。题解将特征串一一插入AC自动机并构建fail指针,这样母串匹配的时候走过的路径上的点所代表的前缀就都是可匹配的了。所以把所有...

玄武OnLine Client.exe 的命令行加密方法

朋友让帮忙分析这个游戏的命令行的加密方法 (挺有意思的  这是分析完的LPSTR WINAPI GetXWLoginParam(LPSTR szBuff)//; //至少64字节buff { ...

玄武短信接口和移动MAS短信接口的API封装

直接上代码,关键点: 133行的敏感词过滤 176行的6位扩展码写入   1 using System; 2 using System.Collections.Generic; ...
  • starcrm
  • starcrm
  • 2016年09月18日 17:39
  • 1713

玄武饭店信息管理系统

  • 2006年02月23日 09:05
  • 1.39MB
  • 下载

玄武饭店信息管理系统

  • 2005年12月23日 09:52
  • 0B
  • 下载

Vijos P1449 字符串还原【密码】

背景 小K是一位蔚蓝教主的崇拜者(Orz教主er),有一天,他收到了一封匿名信,信告诉了小K由于他表现出色,得到了一次当面Orz教主的机会,但是要当面Orz教主可不那么容易,不是每个人都有资格Orz...

Vijos 1028-魔族密码【暴力】

风之子刚走进他的考场,就…… 花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花) 风之子:我呕……(杀死人的眼神)快说题目!否则……-_-### 花花:……咦~~好冷~~我们现在要...

Vijos P1028魔族密码

描述 风之子刚走进他的考场,就…… 花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花) 风之子:我呕……(杀死人的眼神)快说题目!否则……-_-### 花花:……咦~~好冷~~我...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:vijos-1951 玄武密码
举报原因:
原因补充:

(最多只允许输入30个字)