【AC自动机】玄武密码

【题目链接】

https://loj.ac/problem/10058

【题意】

对于每一段文字,其前缀在母串上的最大匹配长度是多少呢

【参考别人的题解】

https://www.luogu.org/problemnew/solution/P5231

我们只需要先建立所有密码的trie树
再以母串为主串跑一个AC自动机
不过其中还是有一些需要改动的地方
原本字典树中用来记录某个节点是不是字符串结尾的数组不需要,直接删去
我们需要另一个数组来标记哪些点被匹配
跑完ac自动机后从trie树上找最后一个匹配的点即可
优化:由于nxt数组是递归到0的所以只要有一个点被标记过,那么这个点到0的所有点都已经被遍历过直接退出即可

【自己理解】

其实这个题目就是套路。

1、建模式串的AC自动机。

2、利用文本串跑一遍AC自动机,把对应的位置标记上。

3、再跑一遍模式串,去最长的位置就是答案了。

【代码】

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int M = 2e7 + 5 ;
 6 const int N = 2e5+5 ;
 7 char T[M];
 8 char P[N][205];
 9 int Trie[M][4],Match[M],fail[M],Cnt[M];
10 int Q[M],Head,Tail;
11 int n,m,idx=1;
12
13 int calc( char x ){
14     if( x == ‘N‘ ) return 0;
15     else if( x==‘E‘ ) return 1;
16     else if( x==‘S‘ ) return 2;
17     else return 3;
18 }
19 void Insert(char s[],int Id){
20     int p = 1;
21     for(int i=0;s[i];i++){
22         int t = calc(s[i]);
23         if( !Trie[p][t] )
24             Trie[p][t] = ++idx ;
25         p = Trie[p][t];
26     }
27     Match[Id] = p ;
28 }
29 void Build(){
30     Head = 1 , Tail = 0 ;
31     for(int i=0;i<4;i++) Trie[0][i] = 1;
32
33     Q[++Tail] = 1 ;
34     while( Head <= Tail ){
35         int u = Q[Head++] ;
36         for(int i=0;i<4;i++){
37             int To = Trie[u][i];
38             if( To ){
39                 fail[To] = Trie[fail[u]][i];
40                 Q[ ++Tail ] = To ;
41             }else{
42                 Trie[u][i] = Trie[fail[u]][i];
43             }
44         }
45     }
46 }
47 void Query(char T[]){
48
49     int p = 1 ;
50     for(int i=0;T[i];i++){
51         p = Trie[p][calc(T[i])];
52         for(int j=p;j;j=fail[j]){
53             if( Cnt[j] ) break;
54             Cnt[j] = 1 ;
55         }
56     }
57
58     for(int i=1;i<=m;i++){
59         int res = 0 , p = 1 ;
60         for(int j=0;P[i][j];j++){
61             p = Trie[p][calc(P[i][j])];
62             if( Cnt[p] ) res = j + 1 ;
63         }
64         printf("%d\n",res);
65     }
66 }
67 int main()
68 {
69     scanf("%d%d",&n,&m);
70     scanf("%s",T);
71     for(int i=1;i<=m;i++){
72         scanf("%s",P[i]);
73         Insert( P[i] , i );
74     }
75     Build();
76     Query(T);
77     return 0 ;
78 }

玄武密码

原文地址:https://www.cnblogs.com/Osea/p/11366976.html

时间: 2024-10-03 05:14:52

【AC自动机】玄武密码的相关文章

[AC自动机]玄武密码

题目描述 一个长度为\(N\)的母串,有四个元素分别是:N,S,W,N. 有M个长度为100的模式串. 现在要求每个模式串的前缀与母串匹配最长长度. 输入样例 7 3 SNNSSNS NNSS NNN WSEE 输出样例 4 2 0 题解 这是AC自动机的模板题 关键是判断模式串的前缀是否被匹配 因为AC自动机的一个结点代表一个前缀,通过fail指针的遍历可以标记所有匹配的前缀 首先将模式串插入到trie树中,构造自动机 再将母串输入到AC自动机中,把匹配到的前缀即结点都标记一下.这里有一个剪枝

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

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

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

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

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

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

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

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

[BZOJ1559]密码 AC自动机+状压

问题 K: [JSOI2009]密码 时间限制: 1 Sec  内存限制: 64 MB 题目描述 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝试所有可能的字母组合,但这是一项很耗时又容易被发现的工 作.所以,为了获取对方的登陆口令,在暴力破解密码之前,必须先做大量的准备工作.经 过情报的搜集,现在得到了若干有用信息,形如: “我观察到,密码中含有字符串***.” 例如,对于一个10位的密码以及观察到的字符串hello与world,可能的密

BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )

建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接暴搜答案. 数据范围很小, 可以AC(复杂度懒得算了....) ------------------------------------------------------------------------------------------------ #include<cstdio> #in

[BZOJ1559][JSOI2009]密码(AC自动机)

http://www.lydsy.com/JudgeOnline/problem.php?id=1559 2009年的省选题虽然比起现在简单了不少,但对我来说还是很有挑战性的. 首先对于这种多串匹配问题,第一个想到的就应该是AC自动机. 还是老套路,f[i][j]表示走到字符串的第i位,现在在自动机上的第j位时的信息.增加一维n位的压位表示各个串是否都被匹配到了. 但是这里有个问题,如果S1包含了S2,那么我们只需要S1被匹配就能保证S2也被匹配,而不需要在自动机上走到S2的位置. 这样我们预处

AC自动机 &amp; fail树

[BZOJ 1195] 最短母串 题意 给定 n (n <= 12) 个子串 s (|s| <= 60) , 求一个最短母串. 分析 建 AC 自动机. 设 St 为每个点的状态, 在 fail 树上下传一下. 直接 BFS 找到第一个满的状态 (Node, State) . [BZOJ 4327] [JSOI 2012] 玄武密码 题意 给定一个母串和若干个模式串. 求每个模式串最多能在母串上匹配多少位. |S| <= 10000000, |T| <= 100, m <=