「JSOI2012」玄武密码

「JSOI2012」玄武密码

传送门

题目是要求多个串在母串上的最长匹配长度。

考虑 \(\text{AC}\) 自动机,我们建出 \(\text{Trie}\) 图然后用母串来在上面跑。

每一个能匹配的位置,它 \(\text{fail}\) 的位置也一定可以匹配,我们就跳 \(\text{fail}\) 把经过的节点的值赋为 \(1\) ,表示这个位置可以匹配。

然后我们每一个模式串,找到ta在 \(\text{Trie}\) 树上最深的可以匹配的节点来计算答案即可。

参考代码:

#include <cstring>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
template < class T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while ('0' > c || c > '9') f |= c == '-', c = getchar();
    while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    s = f ? -s : s;
}

const int _ = 1e7 + 5, __ = 1e5 + 5;

char a[_], s[_][102]; int n, m;
int tot, ch[4][_], fail[_], vis[_];

inline int cg(char c) { if (c == 'E') return 0; if (c == 'S') return 1; if (c == 'W') return 2; if (c == 'N') return 3; }

inline void insert(int x) {
    int u = 0, len = strlen(s[x] + 1);
    for (rg int i = 1; i <= len; ++i) {
        int c = cg(s[x][i]);
        if (!ch[c][u]) ch[c][u] = ++tot;
        u = ch[c][u];
    }
}

inline void build() {
    static int hd, tl, Q[_];
    hd = tl = 0;
    for (rg int c = 0; c < 4; ++c) if (ch[c][0]) Q[++tl] = ch[c][0];
    while (hd < tl) {
        int u = Q[++hd];
        for (rg int c = 0; c < 4; ++c) {
            if (!ch[c][u]) ch[c][u] = ch[c][fail[u]];
            else fail[ch[c][u]] = ch[c][fail[u]], Q[++tl] = ch[c][u];
        }
    }
}

inline void query() {
    int u = 0, len = strlen(a + 1);
    for (rg int i = 1; i <= len; ++i) {
        u = ch[cg(a[i])][u];
        for (rg int v = u; v; v = fail[v]) if (!vis[v]) vis[v] = 1; else break ;
    }
}

inline int calc(int x) {
    int u = 0, len = strlen(s[x] + 1), res = 0;
    for (rg int i = 1; i <= len; ++i) {
        u = ch[cg(s[x][i])][u]; if (vis[u]) res = i;
    }
    return res;
}

int main() {
#ifndef ONLINE_JUDGE
    file("cpp");
#endif
    read(n), read(m), scanf("%s", a + 1);
    for (rg int i = 1; i <= m; ++i) scanf("%s", s[i] + 1), insert(i);
    build();
    query();
    for (rg int i = 1; i <= m; ++i) printf("%d\n", calc(i));
    return 0;
}

原文地址:https://www.cnblogs.com/zsbzsb/p/12283521.html

时间: 2024-10-08 14:25:16

「JSOI2012」玄武密码的相关文章

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

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

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

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

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

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

玄武密码(bzoj4327)(JSOI2012)

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

「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉:既可让人明白「为何如此设计」,即「知其然更知其所以然」:也能剥离一些琐碎的细节,让更多没那么多时间与精力.或者背景知识不足的朋友,对核心方法和思路,多一点理解,即,给人提供一种「纲举目张提纲挈领抽丝剥茧」的可能性. 机缘巧合,俺今天就决定抛砖引玉,写一篇不那么好的工程文档.也期望对本文话题感兴趣的朋

正在用华为手机的你,怎能少了这一「神器」

人们总希望有后悔药,能够在意外发生时「倒流时光」.但现实告诉我们的是,世界上根本就没有后悔药,我们能做的只有在意外发生前买好「保险」,将意外造成的风险降到最低,而最近,我发现「买保险」的这一原则同样适用于华为手机. 但别会错意,此「保险」非彼「保险」,并不是说让你真的为手机买一期「机身安全险」,这个保险指的是「华为云空间」,如果你能够善加利用 TA,那么 TA 将能够最大程度地降低你在使用手机时可能会发生的风险. 真的有必要使用手机上的云空间吗? 相信在许多人脑海中,首先浮现的就是这个问题:到底

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

「随笔」基于当下的思考

马德,说好的技术blog,变成日记本了... 下午的时候莫名其妙的感到很颓废,因为自己的不够强大感到忧虑和危机感十足.现在每每行走在技术的道路上,常觉得如履薄冰,如芒在背. 上大学之前和现在的心态其实差别挺大的,视野的开阔远远不止局限于自己的脚下.不过,这里的「上大学之前」只是一个时间描述词,并不觉得大学是最适合学习的地方,我很失望. 世界上的人无论性别,区域,宗教,兴趣爱好,总可以在互联网上找到志趣相同的人,总是可以不断打破自己的常识与惯性思维.总是有在相同领域比自己更强的人,挺好的. 关于知

「Unity」与iOS、Android平台的整合:3、导出的Android-Studio工程

本文属于「Unity与iOS.Android平台的整合」系列文章之一,转载请注明出处. Unity默认导出的是Android-Eclipse工程,毕竟Eclipse for Android开发在近一两年才开始没落,用户量还是非常巨大的. 个人认为AndroidStudio非常好用,能轻易解决很多Eclipse解决不了或者很难解决的问题. 所以我将Unity导出的Andoid工程分为Eclipse和AndroidStudio两部分. 不过我之后的相关内容都会使用AndroidStudio,希望依然