1283. 玄武密码

题目链接

1283. 玄武密码

在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。

相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。

老人们说,这是玄武神灵将天书藏匿在此。

很多年后,人们终于在进香河地区发现了带有玄武密码的文字。

更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联。

于是,漫长的破译工作开始了。

经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为 N 的序列来描述,序列中的元素分别是 E,S,W,N,代表了东南西北四向,我们称之为母串。

而神秘的玄武密码是由四象的图案描述而成的 M 段文字。

这里的四象,分别是东之青龙,西之白虎,南之朱雀,北之玄武,对东南西北四向相对应。

现在,考古工作者遇到了一个难题。

对于每一段文字,其前缀在母串上的最大匹配长度是多少呢?

输入格式

第一行有两个整数,NM,分别表示母串的长度和文字段的个数;

第二行是一个长度为 N 的字符串,所有字符都满足是 E,S,W,N 中的一个;

之后 M 行,每行有一个字符串,描述了一段带有玄武密码的文字。依然满足,所有字符都满足是 E,S,W,N 中的一个。

输出格式

输出有 M 行,对应 M 段文字。

每一行输出一个数,表示这一段文字的前缀与母串的最大匹配串长度。

数据范围

1N107,
1M105,
保证每一段文字的长度均小于等于 100

输入样例:

7 3 SNNSSNS NNSS NNN WSEE

输出样例:

4 2 0

解题思路

后缀自动机

后缀自动机裸题,由于后缀自动机形成的有向无环图恰好能够保存所有不同的子串,即从源点出发,沿任意一些字符能够到达的状态节点形成的子串在原字符串中都存在,故对于有每一个匹配串,都可以直接沿着后缀自动机形成的有向无环图走一遍,当无路可走或走完所有匹配串字符时即找到最长的前缀长度

  • 时间复杂度:O(n+100m)

代码

// Problem: 玄武密码 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/1285/ // Memory Limit: 512 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e7+5; int n,m,cnt=1,lst=1; char s[N]; struct Node { int fa,len; int ch[4]; }node[N<<1]; inline int get(char c) { if(c=='E')return 0; if(c=='S')return 1; if(c=='N')return 2; return 3; } void extend(int c) { int p=lst,np=lst=++cnt; node[np].len=node[p].len+1; for(;p&&!node[p].ch[c];p=node[p].fa)node[p].ch[c]=np; if(!p)node[np].fa=1; else { int q=node[p].ch[c]; if(node[q].len==node[p].len+1)node[np].fa=q; else { int nq=++cnt; node[nq]=node[q]; node[nq].len=node[p].len+1; node[q].fa=node[np].fa=nq; for(;p&&node[p].ch[c]==q;p=node[p].fa)node[p].ch[c]=nq; } } } int main() { scanf("%d%d",&n,&m); scanf("%s",s); for(int i=0;s[i];i++)extend(get(s[i])); while(m--) { scanf("%s",s); int p=1,res=0; for(int i=0;s[i];i++) { int c=get(s[i]); if(!node[p].ch[c])break; p=node[p].ch[c]; res++; } printf("%d\n",res); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16225974.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示