AC自动机玄武密码

Posted osea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 
玄武密码

 

以上是关于AC自动机玄武密码的主要内容,如果未能解决你的问题,请参考以下文章

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

[AC自动机]玄武密码

AC自动机bzoj4327: JSOI2012 玄武密码

bzoj4327JSOI2012 玄武密码 AC自动机

「学习笔记」AC 自动机

[JSOI 2012] 玄武密码