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 ...
随机推荐
- 搭建mongoDB 配置副本集 replSet
mongodb的master_slave和ReplSet是很常见的两种构架: 下面记录下搭建mongodbReplSet 的过程: 首先,进入到一个指定目录下 >cd /opt 下载mongod ...
- SSH实现在WIN7系统下访问虚拟机中的Linux系统
使用的是centos6.4进行练习的,安装的是vmware8虚拟机.以下是总结的一些步骤: 一.确保vmware使用NAT的连接方式,如做地址.端口映射 首先查看vmware的中网络连接的一些方式:E ...
- iOS开发教程:Storyboard全解析-第一部分
本文转载至http://blog.csdn.net/chang6520/article/details/7945845 感谢原文作者分享 故事版(Storyboard)是一个能够节省你很多设计 ...
- EasyCamera Android安卓移动视频监控单兵设备接入EasyDarwin开源流媒体云平台
前言 随着Android系统的不断更新和发展,现在越来越多的硬件产品选择用安卓系统作为运行环境,电视机,机顶盒.门禁.行车记录仪.车载系统.单兵设备等等,Android系统底层还是Linux,但对上层 ...
- Hibernate中的HQL语言
一.HQL语言简介 HQL全称是Hibernate Query Language,它提供了是十分强大的功能,它是针对持久化对象,直接取得对象,而不进行update,delete和insert等操作.而 ...
- 给js设定一个统一的入口
javascript是种脚本语言,浏览器下载到哪儿就会运行到哪儿,这样的特性会为编程提供方便,但也easy使程序过于凌乱.支离破碎. js从功能上能够分为两大部分--框架部分和应用部分,框架部分提供的 ...
- C++ xml 解析器
C++的xml解析器有很多,这个知乎回答里有一个列表:https://www.zhihu.com/question/32046606 下面使用其中的RapidXml试试. 官方地址: https:// ...
- [noip2014day1-T3]飞扬的小鸟
Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败. ...
- kernel中对文件的读写【学习笔记】【原创】
/*1. 头文件 */ #include <linux/init.h> #include <linux/module.h> #include <linux/modulep ...
- Django_model进阶
Django-model进阶 QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Ent ...