ZOJ3228【AC自动机】
先贡献几个数据(
没用别怪我):
/*
ab
4
0 ab
1 ab
0 ab
1 ab
abababac
4
0 aba
1 aba
0 abab
1 abab
abcdefghijklmnopqrstuvwxyz
3
0 abc
1 def
1 jmn
abcdabcd
3
0 cd
0 abcd
0 abcd
*/
思路:
因为要考虑不可重复和可重复,而且输入那一堆串还有重复的,如果可以重复,那么就是正常做法,回溯到根,全部相加;如果不可以重复,那么标记位置上的后缀串的长度。
ps:因为是书上例题,然后照着书上代码搞搞搞,没想到搞崩了。因为书上代码是错的!他开了一个flag表示这个位置是否存在后缀串,但是他找的时候= =、第一个错误;还有他没有把fail指针回溯到根,第二个错误,不过这个flag数组搞的很好?(其实并没有。。。贴第一发自己的,第二发书上已改正的代码)
MY CODE
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII; const int N=1e6+10;
int g[600010][26],word[N],fail[N],sz;
char txt[N],ss[N];
int ans[N][2],last[N],len[N],pos[100010],n,id[100010];
int flag[N]; int INS()
{
int p=0;
int lens=strlen(ss);
int index;
for(int i=0;i<lens;i++){
index=ss[i]-'a';
if(g[p][index]==0){
memset(g[sz],0,sizeof(g[sz]));
last[sz]=-1;
flag[sz]=0;
word[sz]=0;
ans[sz][0]=ans[sz][1]=0;
g[p][index]=sz++;
}
p=g[p][index];
}
word[p]=1;
flag[p]=1;
len[p]=lens;
return p;
} void Build_fail()
{
int p=0;
queue<int>que;
for(int i=0;i<26;i++){
if(g[p][i])
{
que.push(g[p][i]);
fail[g[p][i]]=0;
}
}
while(!que.empty())
{
p=que.front();que.pop();
for(int i=0;i<26;i++){
int u=g[p][i];
if(!u)
g[p][i]=g[fail[p]][i];
else{
que.push(u);
int v=fail[p]; //取父节点的fail指针去匹配
while(v && !g[v][i])
v=fail[v];
fail[u]=g[v][i];
}
}
}
} void solve()
{
int p=0;
int index,lens=strlen(txt);
for(int i=0;i<lens;i++)
{
index=txt[i]-'a';
p=g[p][index];
int temp=p;
while(temp){ //回溯到根
if(word[temp])
{
ans[temp][0]++;
if((i-last[temp])>=len[temp])
{
ans[temp][1]++;
last[temp]=i;
}
}
temp=fail[temp];
}
}
} int main()
{
int cas=1;
while(~scanf("%s",txt))
{
memset(g[0],0,sizeof(g[0]));
sz=1;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%s",&id[i],ss);
pos[i]=INS();
}
Build_fail();
solve();
// for(int i=1;i<sz;i++)
// printf("%d %d\n",ans[i][0],ans[i][1]);
printf("Case %d\n",cas++);
for(int i=1;i<=n;i++)
printf("%d\n",ans[pos[i]][id[i]]);
puts("");
}
return 0;
}
BOOK CODE
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII; const int N=1e6+10;
int g[600010][26],word[N],fail[N],sz;
char txt[N],ss[N];
int ans[N][2],last[N],len[N],pos[100010],n,id[100010];
int flag[N]; int INS()
{
int p=0;
int lens=strlen(ss);
int index;
for(int i=0;i<lens;i++){
index=ss[i]-'a';
if(g[p][index]==0){
memset(g[sz],0,sizeof(g[sz]));
last[sz]=-1;
flag[sz]=0;
word[sz]=0;
ans[sz][0]=ans[sz][1]=0;
// fail[sz]=0;
g[p][index]=sz++;
}
p=g[p][index];
}
word[p]=1;
flag[p]=1;
len[p]=lens;
return p;
} void Build_fail()
{
int p=0;
queue<int>que;
for(int i=0;i<26;i++){
if(g[p][i])
{
que.push(g[p][i]);
fail[g[p][i]]=0;
}
}
while(!que.empty())
{
p=que.front();que.pop();
for(int i=0;i<26;i++){
int u=g[p][i];
if(!u)
g[p][i]=g[fail[p]][i];
else{
que.push(u);
fail[u]=g[fail[p]][i];
flag[u]|=flag[fail[u]];
}
}
}
} void solve()
{
int p=0;
int index,lens=strlen(txt);
for(int i=0;i<lens;i++)
{
index=txt[i]-'a';
p=g[p][index];
int temp=p;
while(temp&&!flag[temp])
temp=fail[temp];
while(temp){
if(word[temp])
{
ans[temp][0]++;
if((i-last[temp])>=len[temp])
{
ans[temp][1]++;
last[temp]=i;
}
}
temp=fail[temp];
}
}
} int main()
{
int cas=1;
while(~scanf("%s",txt))
{
memset(g[0],0,sizeof(g[0]));
sz=1;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%s",&id[i],ss);
pos[i]=INS();
}
Build_fail();
solve();
printf("Case %d\n",cas++);
for(int i=1;i<=n;i++)
printf("%d\n",ans[pos[i]][id[i]]);
puts("");
}
return 0;
}
ZOJ3228【AC自动机】的更多相关文章
- zoj3228 Searching the String AC自动机查询目标串中模式串出现次数(分可覆盖,不可覆盖两种情况)
/** 题目:zoj3228 Searching the String 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=34 ...
- 【AC自动机】zoj3228 Searching the String
对所有模式串建立AC自动机. 每个单词结点要记录该单词长度. 然后在跑匹配的时候,对每个单词结点再处理3个值,代表可重叠的匹配次数,不可重叠的匹配次数,以及“上一次不可重叠的匹配位置”,这样结合单词长 ...
- ZOJ3228 Searching the String —— AC自动机 + 可重叠/不可重叠
题目链接:https://vjudge.net/problem/ZOJ-3228 Searching the String Time Limit: 7 Seconds Memory Limi ...
- ZOJ3228 - Searching the String(AC自动机)
题目大意 给定一个文本串,接下来有n个模式串,每次查询模式串出现的次数,查询分两种,可重叠和不可重叠 题解 第一次是把AC自动机构造好,跑n次,统计出每个模式串出现的次数,交上去果断TLE...后来想 ...
- ZOJ3228 Searching the String (AC自动机)
Searching the String Time Limit: 7 Seconds Memory Limit: 129872 ...
- AC自动机基础知识讲解
AC自动机 转载自:小白 还可参考:飘过的小牛 1.KMP算法: a. 传统字符串的匹配和KMP: 对于字符串S = ”abcabcabdabba”,T = ”abcabd”,如果用T去匹配S下划线部 ...
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- python爬虫学习(11) —— 也写个AC自动机
0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
随机推荐
- 无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护
golang/goroutine 和 swoole/coroutine 协程性能测试对比 - Go语言中文网 - Golang中文社区 https://studygolang.com/articles ...
- Kotlin基本语法笔记3之定义类、继承及创建实例
定义类 class MyObject private constructor(name: String, age: Int) { private var name: String private va ...
- 在Qt中使用大漠插件
因工作需要,项目需求(要编写一个营销软件,其中一个功能是控制QQ和微信发送广告消息给指定的联系人或群组, 因为我Windows和逆向水平还不到家,起初的调用Windows API的设计方案不可行,于是 ...
- java读取properties文件中参数值
在类文件中加入代码: //config.properties.sysInfo //sysInfo.properties在文件夹的路径为/src/config/properties/sysInfo.pr ...
- Android 反编译工具
想必玩安卓的童鞋大多都知道,安卓的APK安装包是可以反编译出源代码的,如果开发人员发布时没有对其混淆等加密处理,反编译出来的代码几乎与真实的源代码一模一样. 想要反编译apk,需要用到apktool. ...
- jquery中attr和prop的区别—判断复选框选中状态
最近项目中需要用jquery判断input里checkbox是否被选中,发现用attr()获取不到复选框改变后的状态,最后查资料发现jQuery 1.6以后新增加了prop()方法,借用官方的一段描述 ...
- tomcat 启动增加参数
linux: JAVA_OPTS="$JAVA_OPTS -Dconfig.type=inte2 -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:Max ...
- SVN与CVS比较-怎度网
SVN与CVS比较 所有的文档都显示SVN可以取代CVS,同时SVN的问题和缺点都被隐藏了.不幸的是,我们并不认为SVN是CVS的替代品,尽管很多缺陷都被修改了.更有甚者,它甚至让人重回VSS.CVS ...
- Service的两种启动方式
今天又写Service,提示覆写onBind(),想起Android好像是有个叫做Binder的IPC机制. Service里面有一个onBind(),一个onStartCommand(),两者都能启 ...
- luogu 3812 【模板】 线性基
线性基是一个支持在集合里插入数并查询最大子集异或值 #include<iostream> #include<cstdio> #include<cstring> #i ...