ZOJ   3228

题目网址:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=16401

Description

Little jay really hates to deal with string. But moondy likes it very much, and she's so mischievous that she often gives jay some dull problems related to string. And one day, moondy gave jay another problem, poor jay finally broke out and cried, " Who can help me? I'll bg him! "

So what is the problem this time?

First, moondy gave jay a very long string A. Then she gave him a sequence of very short substrings, and asked him to find how many times each substring appeared in string A. What's more, she would denote whether or not founded appearances of this substring are allowed to overlap.

At first, jay just read string A from begin to end to search all appearances of each given substring. But he soon felt exhausted and couldn't go on any more, so he gave up and broke out this time.

I know you're a good guy and will help with jay even without bg, won't you?

Input

Input consists of multiple cases( <= 20 ) and terminates with end of file.

For each case, the first line contains string A ( length <= 10^5 ). The second line contains an integer N ( N <= 10^5 ), which denotes the number of queries. The next N lines, each with an integer type and a string a ( length <= 6 ), type = 0 denotes substring a is allowed to overlap and type = 1 denotes not. Note that all input characters are lowercase.

There is a blank line between two consecutive cases.

Output

For each case, output the case number first ( based on 1 , see Samples ).

Then for each query, output an integer in a single line denoting the maximum times you can find the substring under certain rules.

Output an empty line after each case.

Sample Input

ab
2
0 ab
1 ab abababac
2
0 aba
1 aba abcdefghijklmnopqrstuvwxyz
3
0 abc
1 def
1 jmn

Sample Output

Case 1
1
1 Case 2
3
2 Case 3
1
1
0

Hint

In Case 2,you can find the first substring starting in position (indexed from 0) 0,2,4, since they're allowed to overlap. The second substring starts in position 0 and 4, since they're not allowed to overlap.

For C++ users, kindly use scanf to avoid TLE for huge inputs.

题意:给了N个模式串,然后又给了一个长串,求每个模式串在这个长串中出现的次数。每个模式串前给了类型限制,若为0,表示串可以重叠,1表示不能重叠。

思路:当为0类型时,可以重叠,则和以前的AC自动机模板一样,1时,需要在模式串的最后一个字符的结构体内标识一下上一次这个串在长串中出现的位置,当再次匹配到这个串的末尾时,用当前串的位置序号减去上次出现的位置序号,若长大于等于模式串的长度,则串出现次数加一。注意:相同的串并且是相同类型的串可能出现多次,如 0 aba ,0 aba

所以可以在字符结构体中记录0型和1型串出现次数,记录输入的模式串,最后按顺序输出时,将对应的串和类型数传到trie树中查找,返回输出记录0型和1型串出现的次数。

参考别人的代码如下:

#include <stdio.h>
#include <string.h>
#include <memory.h>
struct node{
node *fail;
node *next[];
int id;
node(){
fail=NULL;
id=;
memset(next,NULL,sizeof(next));
}
}*q[],*root;
int head,tail;
char str1[][],str2[];
int A[],cnt[][],pos[],Len[],n;
void insert_Trie(char *str,int num1){
node *p=root;
int i=,id;
while(str[i]){
id=str[i]-'a';
if(p->next[id]==NULL) p->next[id]=new node();
p=p->next[id];i++;
}
p->id=num1;
}
int search_1(char *str){
node *p=root;
int m,i=;
while(str[i]){
m=str[i]-'a';
if(p->next[m]==NULL) return -;
p=p->next[m];
i++;
}
return p->id;
}
void setfail() ///初始化fail指针,BFS
{
q[tail++]=root;
while(head!=tail)
{
node *p=q[head++];
node *temp=NULL;
for(int i=;i<;i++)
if(p->next[i]!=NULL)
{
if(p==root) ///首字母的fail必指向根
p->next[i]->fail=root;
else
{
temp=p->fail; ///失败指针
while(temp!=NULL) ///2种情况结束:匹配为空or找到匹配
{
if(temp->next[i]!=NULL) ///找到匹配
{
p->next[i]->fail=temp->next[i];
break;
}
temp=temp->fail;
}
if(temp==NULL) ///为空则从头匹配
p->next[i]->fail=root;
}
q[tail++]=p->next[i]; ///入队
}
}
} void query(){
int i=;
node *p=root,*temp;
while(str2[i]){
int id=str2[i]-'a';
while(p->next[id]==NULL&&p!=root) p=p->fail;
p=p->next[id];
p=(p==NULL)?root:p;
temp=p;
while(temp!=root){
if(temp->id){
cnt[temp->id][]++;
}
temp=temp->fail;
}
i++;
}
}
void query1(){
int i=;
node *p=root,*temp;
while(str2[i]){
int id=str2[i]-'a';
while(p->next[id]==NULL&&p!=root) p=p->fail;
p=p->next[id];
p=(p==NULL)?root:p;
temp=p;
while(temp!=root){
if(temp->id&&i-pos[temp->id]>=Len[temp->id]){
pos[temp->id]=i;
cnt[temp->id][]++;
}
temp=temp->fail;
}
i++;
}
}
int query_num(char *str,int aa){
int i=;
node *p=root;
while(str[i]){
int id=str[i]-'a';
p=p->next[id];
i++;
}
return cnt[p->id][aa];
}
void del(node *p){
if(p==NULL)return ;
for(int i=;i<;i++)del(p->next[i]);
delete p;
}
int main(){
int t=;
while(scanf("%s",str2)!=-){
scanf("%d",&n);
head=;
tail=;
root=new node();
memset(cnt,,sizeof(cnt));
memset(pos,-,sizeof(pos));
for(int i=;i<=n;i++){
scanf("%d%s",&A[i],str1[i]);
Len[i]=strlen(str1[i]);
insert_Trie(str1[i],i);
}
setfail();
query();
query1();
printf("Case %d\n",t++);
for(int i=;i<=n;i++){
int ttt=query_num(str1[i],A[i]);
printf("%d\n",ttt);
}
printf("\n");
del(root);
}
return ;
}

我的代码如下:(我写的代码很清晰,各种样例都测试通过了,但提交就是wa,唉~)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 770010
char str[],keyword[][];
int head,tail,key[]; struct node
{
node *fail;
node *next[];
int f;
int count1;
int count2;
int b,l;
node()
{
fail=NULL;
count1=;
count2=;
f=-;
b=;
l=;
for(int i=;i<;i++)
next[i]=NULL;
}
}*q[N];
node *root; int insert(char *str,int x) ///建立Trie
{
int temp,len;
node *p=root;
len=strlen(str);
for(int i=;i<len;i++)
{
temp=str[i]-'a';
if(p->next[temp]==NULL)
p->next[temp]=new node();
p=p->next[temp];
}
p->f++;
p->l=len;
if(!x) return p->count1;
else return p->count2;
} void setfail() ///初始化fail指针,BFS
{
q[tail++]=root;
while(head!=tail)
{
node *p=q[head++];
node *temp=NULL;
for(int i=;i<;i++)
if(p->next[i]!=NULL)
{
if(p==root) ///首字母的fail必指向根
p->next[i]->fail=root;
else
{
temp=p->fail; ///失败指针
while(temp!=NULL) ///2种情况结束:匹配为空or找到匹配
{
if(temp->next[i]!=NULL) ///找到匹配
{
p->next[i]->fail=temp->next[i];
break;
}
temp=temp->fail;
}
if(temp==NULL) ///为空则从头匹配
p->next[i]->fail=root;
}
q[tail++]=p->next[i]; ///入队
}
}
} void query()
{
int index,len;
node *p=root;
len=strlen(str);
for(int i=;i<len;i++)
{
index=str[i]- 'a';
while(p->next[index]==NULL&&p!=root) ///跳转失败指针
p=p->fail;
p=p->next[index];
if(p==NULL)
p=root;
node *temp=p; ///p不动,temp计算后缀串
while(temp!=root&&temp->f!=-)
{
temp->count1++;
if(temp->b==||(i-temp->b)>=(temp->l))
{
temp->count2++;
temp->b=i;
}
temp=temp->fail;
}
}
}
void free_(node *r)
{
for(int i=; i<; i++)
{
if(r->next[i])
free_(r->next[i]);
}
free(r);
} int main()
{
int num,Case=;
while(~scanf("%s",str))
{
head=tail=;
memset(key,,sizeof(key));
root = new node();
scanf("%d", &num);
for(int i=;i<=num;i++)
{
scanf("%d %s",&key[i],keyword[i]);
insert(keyword[i],i);
}
setfail();
query();
printf("Case %d\n",Case++);
for(int i=;i<=num;i++)
{
printf("%d\n",insert(keyword[i],key[i]));
}
printf("\n");
free_(root);
}
return ;
}

AC自动机---Searching the String的更多相关文章

  1. ZOJ 3228 Searching the String(AC自动机)

    Searching the String Time Limit: 7 Seconds      Memory Limit: 129872 KB Little jay really hates to d ...

  2. zoj3228 Searching the String AC自动机查询目标串中模式串出现次数(分可覆盖,不可覆盖两种情况)

    /** 题目:zoj3228 Searching the String 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=34 ...

  3. ZOJ3228 Searching the String —— AC自动机 + 可重叠/不可重叠

    题目链接:https://vjudge.net/problem/ZOJ-3228 Searching the String Time Limit: 7 Seconds      Memory Limi ...

  4. ZOJ3228 Searching the String (AC自动机)

    Searching the String Time Limit: 7 Seconds                                      Memory Limit: 129872 ...

  5. 【ZOJ 3228】Searching the String 【AC自动机】

    题意 给出n个模式串和一个文本串,输出各个模式串在文本串中出现的次数.模式串有两种类型,0类型代表可以有重叠,1类型代表不能有重叠.模式串可能出现重复. 分析 算是AC自动机的模板题? 因为模式串可以 ...

  6. Searching the String ZOJ - 3228 AC自动机查询升级版

    题意:先给你一个不超过1000000长度的大串s:接下来输入一个n代表接下来输入的小串个数,小串长度不超过6. 小串分两种类型0和1类型. 0类型表示小串在大串中的最大匹配个数就是常规的AC自动机的做 ...

  7. ZOJ3228 - Searching the String(AC自动机)

    题目大意 给定一个文本串,接下来有n个模式串,每次查询模式串出现的次数,查询分两种,可重叠和不可重叠 题解 第一次是把AC自动机构造好,跑n次,统计出每个模式串出现的次数,交上去果断TLE...后来想 ...

  8. 【AC自动机】zoj3228 Searching the String

    对所有模式串建立AC自动机. 每个单词结点要记录该单词长度. 然后在跑匹配的时候,对每个单词结点再处理3个值,代表可重叠的匹配次数,不可重叠的匹配次数,以及“上一次不可重叠的匹配位置”,这样结合单词长 ...

  9. 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组

    F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...

随机推荐

  1. Windows 64位 安装Oracle instantclient 官方绿色版和PL/SQL Developer 总结

    原文: http://blog.csdn.net/kimsoft/article/details/8751267 操作系统:Windows 7 64位旗舰 要求,安装PL/SQL Developer用 ...

  2. Win 8.1 下 安装 SQL2005

    1.http://blog.csdn.net/lvjin110/article/details/25122879 2.SQL2005版本 需要是  SQL2005开发版

  3. Win7 64位 Visio反向工程(MySQL)

    1 看Office的版本,我安装的是32位的版本,故要去MySQL的官网下载对应32位的ODBC驱动: http://dev.mysql.com/downloads/connector/odbc/ 2 ...

  4. 使用Xcode6.1.1打包出现Your account already has a valid iOS Distribution certificate问题

    1.问题描述: 使用客户证书在Xcode6.1.1上进行打包测试,出现如下问题,查看网上也很多类似错误且解决办法各异. 2.我的解决办法: 让客户将开发.发布证书重新revoke掉之后重新创新并给到p ...

  5. 入手Cubieboard2之制作最小Linux系统

    前言 昨天终于入手了一块Cubieboard2板子,今年4月入职从事的就是与之相关的工作,因此趁现在有时间就好好熟悉一下. 一.主机环境 1.PC主机WIN 7旗舰版 1.虚拟机VM7.0 2.ubu ...

  6. 单线程vs多线程

    a.多线程可以说是实现异步的一种方式: b.共同点:多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性: c.线程消费CPU资源.  异步消费硬件资源: 1.多线程和异步操作 ...

  7. win7任务栏还原为xp样式

    win7的确是非常强大的操作系统,值得一提的是超级任务栏,非常新颖,不过,不是很适应win7的超级任务栏,今天,我们恢复win7超级任务栏还原xp任务栏. 方法/步骤: 1.在win7超级任务栏空白处 ...

  8. linux_脚本应用

    linux下三个有用的 Python 脚本 2010年4月29日   import os, sys  def pyc_clean(dir):      findcmd = 'find %s -name ...

  9. java实例练习

    1.不使用中间变量交换两个数 public class Exchange { public static void main(String[] args) { Scanner scanner = ne ...

  10. 利用Cydia Substrate进行Android HOOK(二)

    在前面关于Substrate的介绍中我们已经讲了用Substrate hook java代码,现在我们讲下怎么用它hook native代码.hook native代码我们需要编写Substrate ...