玄武密码

给若干模式串和一个文本串.求每个模式串在文本串上能匹配的最大前缀长度.

N<=107,M<=105,每一段文字的长度<=100。

jklover的题解

将模式串建成一个 AC 自动机,匹配文本串的时候往前暴力跳,跳到第一个合法的位置即可.

时间复杂度:线性。

co int N=1e7+1,S=4;
int n,m;
int len[N];
namespace AC
{
int idx; int id(char x)
{
switch(x)
{
case 'E':
return 0;
case 'W':
return 1;
case 'N':
return 2;
case 'S':
return 3;
default:
assert(0);
}
} int ch[N][S],fa[N],fail[N];
int marked[N],val[N]; void ins(char s[],int v)
{
int u=0;
for(int i=0;i<len[v];++i)
{
int k=id(s[i]);
if(!ch[u][k])
{
fa[++idx]=u;
ch[u][k]=idx;
}
u=ch[u][k];
}
val[v]=u;
} void getfail()
{
std::queue<int>Q;
for(int i=0;i<S;++i)
if(ch[0][i])
Q.push(ch[0][i]);
while(Q.size())
{
int u=Q.front();Q.pop();
for(int i=0;i<S;++i)
{
if(ch[u][i])
{
fail[ch[u][i]]=ch[fail[u]][i];
Q.push(ch[u][i]);
}
else
ch[u][i]=ch[fail[u]][i];
}
}
} void mark(char*s)
{
int u=0;
for(int i=0;i<n;++i)
{
int k=id(s[i]);
u=ch[u][k];
for(int j=u;j&&!marked[j];j=fail[j])
marked[j]=1;
}
} int work(int x)
{
int ans=len[x];
for(int i=val[x];i;i=fa[i],--ans)
if(marked[i])
return ans;
}
}
char buf[110];
char s[N]; int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(m);
scanf("%s",s);
for(int i=1;i<=m;++i)
{
scanf("%s",buf);
len[i]=strlen(buf);
AC::ins(buf,i);
}
AC::getfail();
AC::mark(s);
for(int i=1;i<=m;++i)
{
int ans=AC::work(i);
printf("%d\n",ans);
}
return 0;
}

Keywords Search

给若干个模式串,再给一个文本串,问有几个模式串在文本串中出现过.

jklover的题解

板子题.注意一个模式串只被计算一次,统计后做上标记.

这里采用的是补全 Trie 树的写法.

时间复杂度线性。主要是找出现的这里:

for(int j=u;j&&val[j]!=-1;j=fail[j])
res+=val[j],val[j]=-1;

但这里每个节点最多访问一次,也是线性的。

可以用蓝书上的last代替。

代码

HDU不给用<bits/stdc++.h>……

co int N=5e5+1,S=26;

namespace AC
{
int idx;
int ch[N][S],fail[N],val[N]; void init()
{
idx=0;
memset(val,0,sizeof val);
memset(ch,0,sizeof ch);
memset(fail,0,sizeof fail);
} void ins(char s[],int n)
{
int u=0;
for(int i=0;i<n;++i)
{
int k=s[i]-'a';
if(!ch[u][k])
ch[u][k]=++idx;
u=ch[u][k];
}
++val[u];
} void getfail()
{
std::queue<int>Q;
for(int i=0;i<S;++i)
if(ch[0][i])
Q.push(ch[0][i]);
while(Q.size())
{
int u=Q.front();Q.pop();
for(int i=0;i<S;++i)
{
if(ch[u][i])
{
fail[ch[u][i]]=ch[fail[u]][i];
Q.push(ch[u][i]);
}
else
ch[u][i]=ch[fail[u]][i];
}
}
} int query(char s[],int n)
{ int u=0,res=0;
for(int i=0;i<n;++i)
{
int k=s[i]-'a';
u=ch[u][k];
for(int j=u;j&&val[j]!=-1;j=fail[j])
res+=val[j],val[j]=-1;
}
return res;
}
}
char buf[N*2]; int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int t;
read(t);
while(t--)
{
AC::init();
int n;
read(n);
for(int i=1;i<=n;++i)
{
scanf("%s",buf);
AC::ins(buf,strlen(buf));
}
AC::getfail();
scanf("%s",buf);
int ans=AC::query(buf,strlen(buf));
printf("%d\n",ans);
}
return 0;
}

JSOI2012 玄武密码 和 HDU2222 Keywords Search的更多相关文章

  1. 【BZOJ4327】JSOI2012 玄武密码 AC自动机

    [BZOJ4327]JSOI2012 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香 ...

  2. 4327: JSOI2012 玄武密码

    4327: JSOI2012 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老 ...

  3. 4327: JSOI2012 玄武密码[SAM]

    4327: JSOI2012 玄武密码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 263  Solved: 112[Submit][Status] ...

  4. P5231 [JSOI2012]玄武密码

    P5231 [JSOI2012]玄武密码 链接 分析: 首先对所有询问串建立AC自动机,然后扫描一遍母串,在AC自动机上走,没走到一个点,标记这个点走过了,并且它的fail树上的祖先节点也可以访问到( ...

  5. HDU2222 Keywords Search 【AC自动机】

    HDU2222 Keywords Search Problem Description In the modern time, Search engine came into the life of ...

  6. 2021.11.10 P5231 [JSOI2012]玄武密码(AC自动机)

    2021.11.10 P5231 [JSOI2012]玄武密码(AC自动机) https://www.luogu.com.cn/problem/P5231 题意: 给出字符串S和若干T,求S与每个T的 ...

  7. AC自动机讲解+[HDU2222]:Keywords Search(AC自动机)

    首先,有这样一道题: 给你一个单词W和一个文章T,问W在T中出现了几次(原题见POJ3461). OK,so easy~ HASH or KMP 轻松解决. 那么还有一道例题: 给定n个长度不超过50 ...

  8. hdu2222 Keywords Search ac自动机

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 题目: Keywords Search Time Limit: 2000/1000 MS ...

  9. HDU2222 Keywords Search [AC自动机模板]

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

随机推荐

  1. flask 密钥问题

    RuntimeError RuntimeError: The session is unavailable because no secret key was set. Set the secret_ ...

  2. LeetCode 179. 最大数(Largest Number) 21

    179. 最大数 179. Largest Number 题目描述 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数. 每日一算法2019/5/24Day 21LeetCode179. La ...

  3. LeetCode 442. 数组中重复的数据(Find All Duplicates in an Array) 17

    442. 数组中重复的数据 442. Find All Duplicates in an Array 题目描述 Given an array of integers, 1 ≤ a[i] ≤ n (n ...

  4. LeetCode 671. 二叉树中第二小的节点(Second Minimum Node In a Binary Tree) 9

    671. 二叉树中第二小的节点 671. Second Minimum Node In a Binary Tree 题目描述 给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 ...

  5. SVN增加访问用户

    1.在Linux中进入SVN配置文件目录. 2.authz是设置权限的,只读还是可读可写,passwd是增加访问用户的. vim passwd; vim authz;

  6. 长乐培训Day6

    T1 数列 题目 [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [数据规模] 如上所述. 解析 身为T1,居然比T4还难......让我怎么办......以下为巨佬题解: 我猜 ...

  7. 第五章 模块之 logging、copy、re

    5.12 logging 日志模块 报警等级 CRITICAL = 50 # 最高FATAL = CRITICALERROR = 40WARNING = 30WARN = WARNINGINFO = ...

  8. sidecar-inject代码分析

    Istio通过对serviceMesh中的每个pod注入sidecar,来实现无侵入式的服务治理能力.其中,sidecar的注入是其能力实现的重要一环(本文主要介绍在kubernetes集群中的注入方 ...

  9. An unavoidable detour for home CodeForces - 814E (dp)

    大意: 给定一棵树每个点的度数, 求所有满足条件的树的个数 每个点到$1$的最短路唯一 假设$l_i$为点$i$到$1$的最短距离, 那么$l_i\ge l_{i-1}$ 每个点度数范围$2\le d ...

  10. MSMQ消息队列,包括远程访问

    之前的项目用到了队列,现在总结一下,下面有非常详细的DEMO,希望能对有需要的人提供帮助. 使用场景:在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了 ...