ZOJ 3228Searching the String

来源:互联网 发布:软件板块股票行情 编辑:程序博客网 时间:2024/06/06 15:46

给定一个模式串和n个目标串和对应的权值,当为0时求目标串在模式串里的出现次数(可重叠),当为1是可重叠。主要还是利用fail指针进行判断,当可重叠时直接累加end数组就可,不可重叠时需记录当前串的长度l和之前匹配到的最大下标p,如果l+p<=当前下标i的话即可加上end数组。代码如下

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<queue>using namespace std;const int INF=1e9;const int MOD=20090717;struct Tree{int next[600010][26],deep[600010],fail[600010];int L,root;int newnode(){for(int i=0;i<26;i++){next[L][i]=-1;}L++;return L-1;}void init(){L=0;root=newnode();deep[root]=0;}int insert(char *s){int len=strlen(s);int p=root;for(int i=0;i<len;i++){int id=s[i]-'a';if(next[p][id]==-1){next[p][id]=newnode();deep[next[p][id]]=deep[p]+1;}p=next[p][id];}return p;}void build(){queue<int>q;int p=root;fail[root]=root;for(int i=0;i<26;i++){//printf("%d %d %d\n",i,p,next[p][i]);if(next[p][i]==-1){next[p][i]=root;}else{fail[next[p][i]]=root;q.push(next[p][i]);}}while(!q.empty()){p=q.front();q.pop();  for(int i=0;i<26;i++){if(next[p][i]==-1){next[p][i]=next[fail[p]][i];}else{fail[next[p][i]]=next[fail[p]][i];q.push(next[p][i]);}}}}int cnt[2][600010];int last[600010];void query(char *s){int len=strlen(s);int p=root,ans=0;memset(cnt,0,sizeof(cnt));memset(last,-1,sizeof(last));for(int i=0;i<len;i++){int id=s[i]-'a';p=next[p][id];int temp=p;while(temp!=root){cnt[0][temp]++;if(i-last[temp]>=deep[temp]){cnt[1][temp]++;last[temp]=i;}temp=fail[temp];}}}/*void debug()    {        for(int i = 0;i < L;i++)        {            printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);            for(int j = 0;j < 26;j++)                printf("%2d",next[i][j]);            printf("]\n");        }    }*/};Tree ac;char str[100010];char s[10];int typ[100010],pos[100010];int main(){int cas=1;int n;while(~scanf("%s",str)){ac.init();scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d %s",&typ[i],s);pos[i]=ac.insert(s);}ac.build();ac.query(str);printf("Case %d\n",cas++);for(int i=0;i<n;i++){printf("%d\n",ac.cnt[typ[i]][pos[i]]);}printf("\n");}}

0 0
原创粉丝点击