您的位置:首页 > 其它

ZOJ 3228 Searching the String(自动机)

2013-04-02 12:55 267 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3441

题意:给定一个串s以及N个子串,问每个子串在s中出现的次数。有些子串允许在s中有重叠有些不允许。

思路:自动机:每个节点记录到达次数,type为1时记录前一次到达时是啥时候。

const int N=200005;

struct node
{
int next[26],fail,cnt[2],pre,len;

void init()
{
clr(next,-1);
fail=-1;
cnt[0]=cnt[1]=0;
pre=-1;
len=0;
}
};

node a
;
int e,n,*mp
;

void insert(char s[],int t,int id)
{
int i,k,p=0;
for(i=0;s[i];i++)
{
k=s[i]-'a';
if(a[p].next[k]==-1)
{
a[e].init();
a[p].next[k]=e++;
}
p=a[p].next[k];
}
a[p].len=i;
mp[id]=&(a[p].cnt[t]);
}

void build()
{
queue<int> Q;
int i,j,k,t,p,q;
Q.push(0);
while(!Q.empty())
{
k=Q.front();
Q.pop();

for(i=0;i<26;i++)
{
if(a[k].next[i]!=-1)
{
p=a[k].next[i];
q=a[k].fail;
while(q!=-1&&a[q].next[i]==-1) q=a[q].fail;
if(q==-1) a[p].fail=0;
else a[p].fail=a[q].next[i];
Q.push(p);
}
else
{
q=a[k].fail;
while(q!=-1&&a[q].next[i]==-1) q=a[q].fail;
if(q==-1) a[k].next[i]=0;
else a[k].next[i]=a[q].next[i];
}
}
}
}

char s
;

void find(char s[])
{
int p=0,i,j,k,t;
for(i=0;s[i];i++)
{
k=s[i]-'a';
p=a[p].next[k];
t=p;
while(t!=-1)
{
if(a[t].len>0)
{
a[t].cnt[0]++;
if(a[t].pre==-1||i-a[t].pre>=a[t].len)
{
a[t].cnt[1]++;
a[t].pre=i;
}
}
t=a[t].fail;
}
}
}

int main()
{
int num=0;
while(scanf("%s",s)!=-1)
{
a[0].init();
e=1;
RD(n);
char str[15];
int i,j;
FOR0(i,n) RD(j),RD(str),insert(str,j,i);
build();
find(s);
printf("Case %d\n",++num);
FOR0(i,n) PR(*mp[i]);
puts("");
}
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: