zoukankan      html  css  js  c++  java
  • 【AC自动机】zoj3228 Searching the String

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

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

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

    Update:加了个优化,仅当某个结点的字符串的后缀可能是单词的时候,才会顺着fail指针往回跳。

    #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;
                  if(word[fail[child[U][i]]])
                    word[child[U][i]]=1;
                  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'];
              }
            if(!word[now])
              continue;
            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
    ",++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
    ",op[i] ? cntb[pos[i]] : cnta[pos[i]]);
            puts("");
          }
        return 0;
    }
  • 相关阅读:
    [设计模式]门面模式
    [设计模式]装饰者模式
    IE8半透明不显示出文字
    解决IE6,IE7不能隐藏绝对定位溢出的内容
    [设计模式]适配器模式
    linux学习网站
    PPP协议解析
    c语言面试题__指针篇
    单链表反转
    16道C语言面试题
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6506324.html
Copyright © 2011-2022 走看看