zoukankan      html  css  js  c++  java
  • HDU 2222(AC自动机模板题)

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2222

    题目大意:多个模式串。问匹配串中含有多少个模式串。注意模式串有重复,所以要累计重复结果。

    解题思路

    AC自动机模板题。

    一开始使用LRJ的坑爹静态模板,不支持重复的模式串。

    在做AC自动机+DP的时候,扒了zcwwzdjn大神的动态优化(失配指向root)写法,以及借鉴了网上的AC自动机模板,

    搞出了这么一个支持重复串的模板。

    注意在计算last后缀链接的时候,都会修改last->cnt=0,是为了防止同一个模式串在匹配时候走了多遍。比如模:AA,匹:AAA,

    修改last->cnt的结果是1,而不修改就是2。修改法在碰到HDU 2896这种需要计算多个匹配串的时候就萎了。

    必须在修改之后,及时恢复。由于本身就使用了queue,所以修改时用queue记录一下哪些last被修改了,之后恢复一下就OK!

    同时,修改法在HDU 3065中,统计一个模式串出现多少次也萎了。因为模式串必须要走多遍。

    #include "cstdio"
    #include "cstring"
    #include "iostream"
    #include "queue"
    #include "string"
    using namespace std;
    struct Trie
    {
        Trie *next[26],*fail;
        int cnt;
    }*root;
    struct status
    {
        Trie *last;
        int cnt;
        status(Trie *last,int cnt):last(last),cnt(cnt) {}
    };
    Trie *newnode()
    {
        Trie *ret=new Trie;
        memset(ret->next,0,sizeof(ret->next));
        ret->fail=0;
        ret->cnt=0;
        return ret;
    }
    void init() {root=newnode();}
    void Insert(string str)
    {
        Trie *pos=root;
        for(int i=0;i<str.size();i++)
        {
            int c=str[i]-'a';
            if(!pos->next[c]) pos->next[c]=newnode();
            pos=pos->next[c];
        }
        pos->cnt++;
    }
    void getfail()
    {
       queue<Trie *> Q;
       for(int c=0;c<26;c++)
       {
           if(root->next[c])
           {
               root->next[c]->fail=root;
               Q.push(root->next[c]);
           }
           else root->next[c]=root;
       }
       while(!Q.empty())
       {
           Trie *x=Q.front();Q.pop();
           for(int c=0;c<26;c++)
           {
               if(x->next[c])
               {
                   x->next[c]->fail=x->fail->next[c];
                   Q.push(x->next[c]);
               }
               else x->next[c]=x->fail->next[c];
           }
       }
    }
    int find(string str)
    {
        Trie *pos=root,*last;
        queue<status> Q;
        int ans=0;
        for(int i=0;i<str.size();i++)
        {
            int c=str[i]-'a';last;
            if(pos->next[c])
            {
                pos=pos->next[c];
                last=pos;
                while(last->cnt)
                {
                    Q.push(status(last,last->cnt));
                    ans+=last->cnt;
                    last->cnt=0; //修改last->cnt
                    last=last->fail;
                }
            }
        }
        while(!Q.empty()) //恢复last->cnt
        {
            status x=Q.front();Q.pop();
            x.last->cnt=x.cnt;
        }
        return ans;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        ios::sync_with_stdio(false);
        int T,n;
        string tt;
        cin>>T;
        while(T--)
        {
            cin>>n;
            init();
            for(int i=1;i<=n;i++)
            {
                cin>>tt;
                Insert(tt);
            }
            getfail();
            cin>>tt;
            int ans=find(tt);
            printf("%d
    ",ans);
        }
    }
    11927003 2014-10-21 01:22:37 Accepted 2222 390MS 29480K 1942 B C++ Physcal
  • 相关阅读:
    在线教程的游戏化-20分钟做了个demo
    (转)内江师院网络专业大二学子实习快报
    学云网线下国信安教育走进川师大
    Ruby on Rails框架开发学习
    Unity3D编程学习分享
    后高考时代规划专家推荐 学云网“学历技能就业”
    Tomcat调优及JMX监控
    XenServer pool 移除server 设置master
    计算程序总行数的Python代码
    SQL Server 无法生成 FRunCM 线程。请查看 SQL Server 错误日志和 Windows 事件日志
  • 原文地址:https://www.cnblogs.com/neopenx/p/4039326.html
Copyright © 2011-2022 走看看