4327: JSOI2012 玄武密码

Description

在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此。 
很多年后,人们终于在进香河地区发现了带有玄武密码的文字。更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联。于是,漫长的破译工作开始了。 
经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素分别是‘E’,‘S’,‘W’,‘N’,代表了东南西北四向,我们称之为母串。而神秘的玄武密码是由四象的图案描述而成的M段文字。这里的四象,分别是东之青龙,西之白虎,南之朱雀,北之玄武,对东南西北四向相对应。 
现在,考古工作者遇到了一个难题。对于每一段文字,其前缀在母串上的最大匹配长度是多少呢? 

Input

第一行有两个整数,N和M,分别表示母串的长度和文字段的个数。 
第二行是一个长度为N的字符串,所有字符都满足是E,S,W和N中的一个。 
之后M行,每行有一个字符串,描述了一段带有玄武密码的文字。依然满足,所有字符都满足是E,S,W和N中的一个。 

Output

输出有M行,对应M段文字。 
每一行输出一个数,表示这一段文字的前缀与母串的最大匹配串长度。 

Sample Input

7 3
SNNSSNS
NNSS
NNN
WSEE

Sample Output

4
2
0

HINT

对于100%的数据,N<=10^7,M<=10^5,每一段文字的长度<=100。

这题虽说是板子,但也不能只用板子,是一道比较不错的AC自动机题目。首先发现多模式串,二话不说上AC自动机,但是发现只有‘E’、‘S’、‘W’、‘N’这四个字母,所以可以优化一下建立起从‘E’、‘S’、‘W’、‘N’到‘a’、‘b’、‘c’、‘d’的映射就好了,然后要查询每个串的前缀与母串的最大匹配长度,那我们就在trie树上标记母串所有的可以匹配到的位置,然后对于每一个模式串,我们就从它的trie树上进行检索,当发现第一个没有被母串匹配到的结点时,当前长度就是最大的匹配长度。另外还有一个小小的优化,如果说对于一个节点它已经被标记过了,那么它的next链上的所有点一定也被标记了,所以这时就可以直接break。

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#define man 100005
#define maxn 10000005
using namespace std; inline int read()
{
char c=getchar();
int res=,x=;
while(c<''||c>'')
{
if(c=='-')
x=-;
c=getchar();
}
while(c>=''&&c<='')
{
res=res*+(c-'');
c=getchar();
}
return res*x;
} int n,m,tot=;
int tree[maxn][],nt[maxn],bo[maxn],f[maxn];
char a[maxn],d[],b[man][];
queue<int>q; char pd(char c)
{
if(c=='E') return d[];
else if(c=='S') return d[];
else if(c=='W') return d[];
else return d[];
} void trie(char *s)
{
int len=strlen(s),u=;
for(register int i=;i<len;i++)
{
int c=s[i]-'a';
if(!tree[u][c])
tree[u][c]=++tot;
u=tree[u][c];
}
bo[u]=;
} void bfs()
{
for(register int i=;i<=;i++)
tree[][i]=;
nt[]=;q.push();
while(q.size())
{
int u=q.front();q.pop();
for(register int i=;i<=;i++)
{
if(!tree[u][i])
tree[u][i]=tree[nt[u]][i];
else
{
int v=tree[u][i];
q.push(v);
nt[v]=tree[nt[u]][i];
}
}
}
} void find(char *s)
{
int len=strlen(s),u=,k;
for(register int i=;i<len;i++)
{
int c=s[i]-'a';
k=tree[u][c];
while(k>)
{
if(f[k]) break;//小小的优化 原理就是这个节点被标记过时,它的
f[k]=;//next链上的点也一点被标记了,所以没必要再跳一次next
k=nt[k];//链,直接break掉就好了。
}
u=tree[u][c];
}
} int ask(char *s)
{
int len=strlen(s),u=;
for(register int i=;i<len;i++)
{
int c=s[i]-'a';
u=tree[u][c];
if(!f[u]) return i;
}
return len;
} int main()
{
n=read();m=read();
d[]='a';d[]='b';d[]='c';d[]='d';
scanf("%s",a);
for(register int i=;i<n;i++)
{
a[i]=pd(a[i]);
}
for(register int i=;i<=m;i++)
{
scanf("%s",b[i]);
int len=strlen(b[i]);
for(register int j=;j<len;j++)
{
b[i][j]=pd(b[i][j]);
}
trie(b[i]);
}
bfs();
find(a);
for(register int i=;i<=m;i++)
{
printf("%d\n",ask(b[i]));
}
return ;
}

4327: JSOI2012 玄武密码的更多相关文章

  1. 4327: JSOI2012 玄武密码[SAM]

    4327: JSOI2012 玄武密码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 263  Solved: 112[Submit][Status] ...

  2. BZOJ 4327: JSOI2012 玄武密码 后缀自动机

    Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) # ...

  3. BZOJ 4327 JSOI2012 玄武密码(后缀自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4327 [题目大意] 求每个子串在母串中的最长匹配 [题解] 对母串建立后缀自动机,用每 ...

  4. BZOJ 4327 [JSOI2012]玄武密码 (AC自动机)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4327 题解: 做法挺显然,建出AC自动机之后在上面跑,标记所有走过的点,然后再进行递推 ...

  5. bzoj 4327: JSOI2012 玄武密码

    听说这题不公开.. 那就不贴题意了 一眼看上去还以为是exkmp的裸题.. 看了数据范围,呵呵.. 多串匹配嘛.. 就用AC自动机咯,而且每个点最多也就只有$4$个孩子 用原串在AC自动机上走,碰到的 ...

  6. 【题解】bzoj 4327 JSOI2012 玄武密码

    原题传送门 我们先对所有询问串建立AC自动机(今天洛咕上有人分不清AC自动机和自动AC机) 然后将母串在AC自动机上跑,每走到一个点x,从x点出发沿着fail指针所能到的所有前缀都是匹配成功的,暴力向 ...

  7. 【BZOJ4327】JSOI2012 玄武密码 AC自动机

    [BZOJ4327]JSOI2012 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香 ...

  8. P5231 [JSOI2012]玄武密码

    P5231 [JSOI2012]玄武密码 链接 分析: 首先对所有询问串建立AC自动机,然后扫描一遍母串,在AC自动机上走,没走到一个点,标记这个点走过了,并且它的fail树上的祖先节点也可以访问到( ...

  9. 2021.11.10 P5231 [JSOI2012]玄武密码(AC自动机)

    2021.11.10 P5231 [JSOI2012]玄武密码(AC自动机) https://www.luogu.com.cn/problem/P5231 题意: 给出字符串S和若干T,求S与每个T的 ...

随机推荐

  1. Python基础:数据类型-列表与元组(6)

    Python中数据结构主要有序列.集合和字典. 1. 通用序列操作 Python内置了多种序列,其中最常用的两种:列表和元组.另一种重要的序列是字符串. 列表和元组的主要不同在于:列表是可以修改的,而 ...

  2. 【pytorch】关于Embedding和GRU、LSTM的使用详解

    1. Embedding的使用 pytorch中实现了Embedding,下面是关于Embedding的使用. torch.nn包下的Embedding,作为训练的一层,随模型训练得到适合的词向量. ...

  3. [2019.03.22] Linux 学习心得(1)

    本文关键词:shell 判断.grep正则表达式使用和贪婪匹配理解 1. if [ $a -le $b ], 一开始自学的时候我以为 [ ... ] 就是普通的,语法规定的结构,结果其实人家是&quo ...

  4. Excel中最精确的计算年龄的公式

    身份证算年龄 假设A1是身份证号所在单元格 =IF(MONTH(NOW())<INT(MID(A1,11,2)),INT(YEAR(NOW())-INT(MID(A1,7,4)))-1,IF(M ...

  5. MySQL数据库开发的三十六条军规

    一.核心军规 尽量不在数据库做运算,cpu计算的事务必移至业务层; 控制表.行.列数量([控制单张表的数据量 1年/500W条,超出可做分表],[单库表数据量不超过300张] .[单张表的字段个数不超 ...

  6. shc & unshc 安装

    shc & unshc 安装 shc 安装 git clone https://github.com/neurobin/shc.git cd shc ./configure make & ...

  7. Python3 找不到库

    import sys sys.path.append('/usr/local/lib64/python3.6/site-packages')sys.path.append('/usr/local/li ...

  8. C#面向对象基本概念总结

    快过年了,发一篇自己的复习总结.以下内容均是个人理解,如文章有幸被浏览,如有错误的地方欢迎大家提出,相互学习相互进步! 面向对象三大基本特征:封装,继承,多态 一.类 (对象声明的三种方式:以普通基类 ...

  9. server.xml配置介绍

    server.xml位于$TOMCAT_HOME/conf目录下,是Tomcat中最重要的配置文件,server.xml的每一个元素都对应了Tomcat中的一个组件:通过对xml文件中元素的配置,可以 ...

  10. PLSQL Developer中文乱码问题

    前言 使用PLSQL工具进行连接远程oracle时,中文乱码 解决过程 1 查看服务器端编码 select userenv('language') from dual; 2 查看客户端编码 执行语句 ...