• 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
    ", find ( rt, 1, i ) );
    71     }
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    vim 命令详解
    vim基础命令
    JSP取得绝对路径
    sigar开发(java)
    HDU-5273
    HDU-1671
    HDU-1251
    POJ-1743
    POJ-2774
    hihocoder 1145 : 幻想乡的日常
  • 原文地址:https://www.cnblogs.com/darklove/p/6022341.html
Copyright © 2020-2023  润新知