bzoj 4327: JSOI2012 玄武密码

听说这题不公开.. 那就不贴题意了

一眼看上去还以为是exkmp的裸题.. 看了数据范围,呵呵..

 

多串匹配嘛.. 就用AC自动机咯,而且每个点最多也就只有$4$个孩子

用原串在AC自动机上走,碰到的和fail到的都是可以到达的字符串,每个点标记记录一下,这个时间复杂度是$O(n)$的

然后再每个串走AC自动机,找到最远的被标记的点就是答案了..

 

 1  
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <queue>
 7 using namespace std;
 8 const int Maxn = 100010;
 9 const int Maxm = 10000010;
10 struct trie {
11     int child[4], fl, fail;
12 }tr[Maxm]; int tot, rt;
13 char s[Maxm], st[Maxn][110]; int n, stl[Maxn];
14 int m;
15 int get ( char c ){
16     if ( c == 'N' ) return 0;
17     if ( c == 'W' ) return 1;
18     if ( c == 'E' ) return 2;
19     return 3;
20 }
21 void bulid ( int &now, int l, int x ){
22     if ( !now ) now = ++tot;
23     if ( l == stl[x]+1 ) return;
24     bulid ( tr[now].child[get(st[x][l])], l+1, x );
25 }
26 void bulid_ac (){
27     queue <int> q;
28     q.push (rt);
29     while ( !q.empty () ){
30         int x = q.front (); q.pop ();
31         for ( int i = 0; i < 4; i ++ ){
32             int y = tr[x].child[i];
33             if ( !y ){
34                 if ( x == rt ) tr[x].child[i] = x;
35                 else tr[x].child[i] = tr[tr[x].fail].child[i];
36             }
37             else {
38                 if ( x == rt ) tr[y].fail = x;
39                 else tr[y].fail = tr[tr[x].fail].child[i];
40             }
41             if ( y > 0 ) q.push (y);
42         }
43     }
44 }
45 int find ( int now, int l, int x ){
46     if ( l == stl[x]+1 ) return stl[x];
47     if ( tr[tr[now].child[get(st[x][l])]].fl == 0 ) return l-1;
48     return find ( tr[now].child[get(st[x][l])], l+1, x );
49 }
50 int main (){
51     int i, j, k;
52     scanf ( "%d%d", &n, &m );
53     scanf ( "%s", s+1 );
54     for ( i = 1; i <= m; i ++ ){
55         scanf ( "%s", st[i]+1 );
56         stl[i] = strlen (st[i]+1);
57         bulid ( rt, 1, i );
58     }
59     bulid_ac ();
60     int now = rt;
61     for ( i = 1; i <= n; i ++ ){
62         now = tr[now].child[get(s[i])];
63         int x = now;
64         while ( tr[x].fl == 0 && x ){
65             tr[x].fl = 1;
66             x = tr[x].fail;
67         }
68     }
69     for ( i = 1; i <= m; i ++ ){
70         printf ( "%d\n", find ( rt, 1, i ) );
71     }
72     return 0;
73 }
View Code

 

posted @ 2016-11-02 11:36  Ra1nbow  阅读(199)  评论(0编辑  收藏  举报