[JSOI 2012] 玄武密码

[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=4327

[算法]

AC自动机
[代码]

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e7 + 10;
const int MAXM = 1e5 + 10;
const int MAXLEN = 110;

int n,m;
int ans[MAXM];
char P[MAXN];
char s[MAXM][MAXLEN];

inline int get_value(char a)
{
        if (a == ‘E‘) return 0;
        if (a == ‘S‘) return 1;
        if (a == ‘W‘) return 2;
        if (a == ‘N‘) return 3;
}
struct AC_Automation
{
        int tot;
        int root;
        struct Node
        {
                int child[4];
                int fail;
                bool visited;
        } trie[MAXN];
        inline void insert(char *s)
        {
                int now = root;
                int len = strlen(s + 1);
                for (int i = 1; i <= len; i++)
                {
                        int val = get_value(s[i]);
                        if (!trie[now].child[val]) trie[now].child[val] = ++tot;
                        now = trie[now].child[val];
                }
        }
        inline void rebuild()
        {
                int l,r;
                static int q[MAXN];
                q[l = r = 1] = root;
                trie[root].fail = -1;
                while (l <= r)
                {
                        int cur = q[l];
                        l++;
                        for (int i = 0; i < 4; i++)
                        {
                                if (trie[cur].child[i])
                                {
                                        if (cur == root)
                                                trie[trie[cur].child[i]].fail = 0;
                                        else
                                        {
                                                int p = trie[cur].fail;
                                                while (p != -1)
                                                {
                                                        if (trie[p].child[i])
                                                        {
                                                                trie[trie[cur].child[i]].fail = trie[p].child[i];
                                                                break;
                                                        } else p = trie[p].fail;
                                                }
                                        }
                                        q[++r] = trie[cur].child[i];
                                 }
                        }
                }
        }
        inline void getans(char *s)
        {
                int now = root;
                int len = strlen(s + 1);
                for (int i = 1; i <= len; i++)
                {
                        int val = get_value(s[i]);
                        int p = now;
                        while (p != -1)
                        {
                                if (trie[p].child[val]) break;
                                else p = trie[p].fail;
                        }
                        if (p == -1)
                        {
                                now = 0;
                                continue;
                        } else now = p = trie[p].child[val];
                        while (p)
                        {
                                if (!trie[p].visited)
                                {
                                        trie[p].visited = true;
                                        p = trie[p].fail;
                                } else break;
                        }
                }
        }
        inline void calc(int pos,char *s)
        {
                int now = root;
                int len = strlen(s + 1);
                for (int i = 1; i <= len; i++)
                {
                        int val = get_value(s[i]);
                        now = trie[now].child[val];
                        if (trie[now].visited) ans[pos] = i;
                }
        }
} ACAM;

int main()
{

        scanf("%d%d",&n,&m);
        scanf("%s",P + 1);
        for (int i = 1; i <= m; i++) scanf("%s",s[i] + 1);
        for (int i = 1; i <= m; i++) ACAM.insert(s[i]);
        ACAM.rebuild();
        ACAM.getans(P);
        for (int i = 1; i <= m; i++) ACAM.calc(i,s[i]);
        for (int i = 1; i <= m; i++) printf("%d\n",ans[i]);

        return 0;

}

原文地址:https://www.cnblogs.com/evenbao/p/9514949.html

时间: 2024-11-02 08:23:37

[JSOI 2012] 玄武密码的相关文章

玄武密码(bzoj4327)(JSOI2012)

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

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

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

VMWare——window server 2008/2012 administrator 密码忘记,设置重置密码

用VMWare安装window server 2008或者2012忘记密码后,想要修改密码满麻烦的. 以下过程是我成功修改密码的过程: 1.首先需要需要链接一个ISO文件 需要特别注意把“启用连接”勾上,这个地方坑了我好长时间.不勾上,系统启动没办法CD-ROM Drive进入的. 2.关闭虚拟机.以下面的方式打开虚拟机: 3进入BIOS界面—>选择Boot:确保启动方式是以CD-ROM Driver 4.然后重新启动.重新启动后,会进入到安装系统界面. 5.点击下一步,在下一个界面左下面,第一

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

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

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

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

【AC自动机】玄武密码

[题目链接] https://loj.ac/problem/10058 [题意] 对于每一段文字,其前缀在母串上的最大匹配长度是多少呢 [参考别人的题解] https://www.luogu.org/problemnew/solution/P5231 我们只需要先建立所有密码的trie树再以母串为主串跑一个AC自动机不过其中还是有一些需要改动的地方原本字典树中用来记录某个节点是不是字符串结尾的数组不需要,直接删去我们需要另一个数组来标记哪些点被匹配跑完ac自动机后从trie树上找最后一个匹配的点

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

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

「JSOI2012」玄武密码

「JSOI2012」玄武密码 传送门 题目是要求多个串在母串上的最长匹配长度. 考虑 \(\text{AC}\) 自动机,我们建出 \(\text{Trie}\) 图然后用母串来在上面跑. 每一个能匹配的位置,它 \(\text{fail}\) 的位置也一定可以匹配,我们就跳 \(\text{fail}\) 把经过的节点的值赋为 \(1\) ,表示这个位置可以匹配. 然后我们每一个模式串,找到ta在 \(\text{Trie}\) 树上最深的可以匹配的节点来计算答案即可. 参考代码: #incl

把数字串变成2012玛雅密码

问题: 玛雅密码是一串由0.1.2组成的密码,这串数字中如果包含2012,就可以解开末日的大门.给定一串由0.1.2组成的字符串,只有相邻的数字可以交换,求通过最少多少次变换可以得到玛雅密码,并给出这串密码. 思路: 经过很久很久的尝试,放弃了一次性拼凑2012的想法,改用预处理得到所有数字范围中符合玛雅密码的部分,再递归遍历给定的数字串,得到该串所有可能的变换,并比较每个变换的结果需要的步数. import sys def find_all_transfers(str): result={}