首页 > 其他 > 详细

【AC自动机】zoj3228 Searching the String

时间:2017-03-05 20:27:09      阅读:156      评论:0      收藏:0      [点我收藏+]

对所有模式串建立AC自动机。

每个单词结点要记录该单词长度。

然后在跑匹配的时候,对每个单词结点再处理3个值,代表可重叠的匹配次数,不可重叠的匹配次数,以及“上一次不可重叠的匹配位置”,这样结合单词长度就能保证不重叠。有多个重叠时,取靠前的位置更优。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>q;
bool word[601000];
int child[601000][26],fail[601000],size,pos[101000];
int cnta[601000],cntb[601000],posn[601000],lens[601000];
void Insert(char S[],int id)
{
    int len=strlen(S);
    int now=0;
    for(int i=0;i<len;++i)
      {
        if(!child[now][S[i]-‘a‘])
          child[now][S[i]-‘a‘]=size++;
        now=child[now][S[i]-‘a‘];
      }
    word[now]=1;
    lens[now]=len;
    pos[id]=now;
}
void build()
{
    fail[0]=-1;
    q.push(0);
    while(!q.empty())
      {
        int U=q.front(); q.pop();
        for(int i=0;i<26;++i)
          if(child[U][i])
            {
              int V=fail[U];
              while(V!=-1)
                {
                  if(child[V][i])
                    {
                      fail[child[U][i]]=child[V][i];
                      break;
                    }
                  V=fail[V];
                }
              if(V==-1)
                fail[child[U][i]]=0;
              q.push(child[U][i]);
            }
      }
}
void match(char S[])
{
    int len=strlen(S);
    int res=0,now=0;
    for(int i=0;i<len;++i)
      {
        if(child[now][S[i]-‘a‘])
          now=child[now][S[i]-‘a‘];
        else
          {
            int U=fail[now];
            while(U!=-1 && child[U][S[i]-‘a‘]==0)
              U=fail[U];
            if(U==-1)
              now=0;
            else
              now=child[U][S[i]-‘a‘];
          }
        int U=now;
        while(U)
          {
          	if(word[U])
          	  {
          	  	++cnta[U];
          	  	if(posn[U]<=i-lens[U])
          	  	  {
          	  	  	++cntb[U];
          	  	  	posn[U]=i;
          	  	  }
          	  }
          	U=fail[U];
          }
      }
}
void Init()
{
    memset(child,0,sizeof(child));
    memset(fail,0,sizeof(fail));
    memset(word,0,sizeof(word));
    memset(pos,0,sizeof(pos));
    memset(cnta,0,sizeof(cnta));
    memset(cntb,0,sizeof(cntb));
    memset(posn,-1,sizeof(posn));
    memset(lens,0,sizeof(lens));
    size=1;
}
char s[101000];
bool op[101000];
int n;
int main()
{
	char ss[9];
	int T=0;
	//freopen("zoj3228.in","r",stdin);
	while(scanf("%s%d",s,&n)!=EOF)
	  {
	  	printf("Case %d\n",++T);
	  	Init();
	  	for(int i=1;i<=n;++i)
	  	  {
	  	  	scanf("%d%s",&op[i],ss);
	  	  	Insert(ss,i);
	  	  }
	  	build();
	  	match(s);
	  	for(int i=1;i<=n;++i)
	  	  printf("%d\n",op[i] ? cntb[pos[i]] : cnta[pos[i]]);
	  	puts("");
	  }
	return 0;
}

【AC自动机】zoj3228 Searching the String

原文:http://www.cnblogs.com/autsky-jadek/p/6506324.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!