题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3228
题目大意: 给出一串主串,然后下面有n串模式串,模式串前面有一个值,
0:在主串中有多少串该模式串,假如aaa 找aa,那么就有2串
1:在主串中有多少串该模式串,并且不能有重叠部分,假如aaa找aa,那么只有1串
题目思路:ac自动机。不知道存不存在相同字符串且相同类型重复询问的情况,为了保险,我还是用了一个hash,将相同的询问hash成一个值,然后将在一个位置里面存两个值,类型0和类型1的id,这样就可以分开计算了,对于类型1,其实就是贪心,只要记录前一次匹配的位置就可以了。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define M 110000
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int q[6*M],cnt;
int hash[M],pre[M],num[M];
char s[M];
char str[10];
int n,m;
struct node
{
int fail,id[2];
int len;
int next[26];
void init()
{
fail=0;
id[0]=id[1]=-1;
memset(next,0,sizeof(next));
}
}tri[6*M];
void insert(char *s,int id,int tp)
{
int i,p,x;
p=0;
for(i=0;s[i];i++)
{
x=s[i]-'a';
if(!tri[p].next[x])
{
tri[++cnt].init();
tri[p].next[x]=cnt;
}
p=tri[p].next[x];
}
if(tri[p].id[tp]==-1)
{
tri[p].id[tp]=id;
hash[id]=id;
tri[p].len=strlen(s);
}
else
{
hash[id]=tri[p].id[tp];
}
}
void bfs()
{
int i,p,suf,head,tail;
p=head=tail=0;
for(i=0;i<26;i++)
{
if(tri[0].next[i])
{
q[tail++]=tri[0].next[i];
tri[q[tail-1]].fail=0;
}
}
while(head<tail)
{
p=q[head++];suf=tri[p].fail;
for(i=0;i<26;i++)
{
if(tri[p].next[i])
{
q[tail++]=tri[p].next[i];
tri[q[tail-1]].fail=tri[suf].next[i];
}
else
tri[p].next[i]=tri[suf].next[i];
}
}
}
void solve()
{
int i,x,p,tmp;
p=0;
for(i=0;s[i];i++)
{
x=s[i]-'a';
p=tri[p].next[x];
tmp=p;
while(tmp)
{
if(tri[tmp].id[0]+1)
{
num[tri[tmp].id[0]]++;
}
if(tri[tmp].id[1]+1)
{
if(pre[tri[tmp].id[1]]!=-1)
{
if(tri[tmp].len<=i-pre[tri[tmp].id[1]])
{
pre[tri[tmp].id[1]]=i;
num[tri[tmp].id[1]]++;
}
}
else
{
pre[tri[tmp].id[1]]=i;
num[tri[tmp].id[1]]++;
}
}
tmp=tri[tmp].fail;
}
}
}
int main()
{
int i,tp,count=1;
while(scanf("%s",s)!=EOF)
{
scanf("%d",&m);
cnt=0;
tri[0].init();
memset(num,0,sizeof(num));
memset(pre,-1,sizeof(pre));
for(i=1;i<=m;i++)
{
scanf("%d%s",&tp,str);
insert(str,i,tp);
}
bfs();
solve();
printf("Case %d\n",count++);
for(i=1;i<=m;i++)
{
printf("%d\n",num[hash[i]]);
}
puts("");
}
}
分享到:
相关推荐
zoj 1610 Count the Colors.md
zoj 1255 The Path.md
ZOJ解题报告ZOJ解题报告ZOJ解题报告ZOJ解题报告
zoj 1810 The Gourmet Club.md
zoj 2499 The Happy Worm.md
zoj 2151 The Highest Profits.md
zoj题目简单归类zoj题目简单归类zoj题目简单归类
acm中zoj1002的可运行C++程序
包含了zoj700多道题目的源代码,在做题时可以参考
String a1a2 ... ap is lexicografically smaller than b1b2 ... bq if there exists an integer i, i , i , such that aj=bj for each j, 1 The director is interested in which of his messages could be read...
Problem Arrangement zoj 3777
ZOJ题目答案源码
一个非常非常非常非常实用的zoj结题代码
学习ACM程序设计的朋友一定要看,这是训练必备的POJ ZOJ题目分类及解题思路
string s1 s2; while cin >> s1 >> s2 { count 0; cout << "[" << endl; if s1 length s2 length BackTrake s1 s2 ; cout << "]" << endl; ...
ZOJ1805代码
zoj 1003 c语言的,要写这么多描述吗。。
本代码是zoj上AC的1951的代码,把双重循环简化为O(n),不过素数判断的改进还不够
zoj1027解题指南和代码,还不错,是学校培训给的。
浙大ZOJ题目分类,可以让你更方便快速锁定那你想要联系的题目,是自己快速提高·