zoukankan      html  css  js  c++  java
  • Keywords Search

    题目大意:输入几个子串,然后输入一个母串,问在母串里面包含几个子串。
     
    分析:刚学习的AC自动机,据说这是个最基础的模板题,所以也是用了最基本的写法来完成的,当然也借鉴了别人的代码思想,确实是个很神奇的东西,如果不懂KMP的话,最好先学学KMP再来学这个,会理解的更深刻一些。
     
    代码如下:
    =======================================================================================================================
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    const int MAXN = 1e6+7;
    const int MAXM = 26;
    const int oo = 1e9+37;
    
    char MumStr[MAXN];///母串
    
    struct Ac_Trie_Node
    {///Fail 失败节点
        Ac_Trie_Node *Fail, *next[MAXM];
        int leaf;///已这个节点为叶子节点的数目
    };
    
    void Insert(Ac_Trie_Node *root, char s[])
    {///插入所有的模式串
        Ac_Trie_Node *p = root;
    
        for(int i=0; s[i]; i++)
        {
            int k = s[i]-'a';
    
            if(p->next[k] == NULL)
                p->next[k] = new Ac_Trie_Node();
            p = p->next[k];
        }
    
        p->leaf += 1;
    }
    void GetFail(Ac_Trie_Node *root)
    {///构造失败指针
        queue<Ac_Trie_Node *> Q;
        Ac_Trie_Node *p = root, *temp;
    
        for(int i=0; i<MAXM; i++)
        {
            if(p->next[i] != NULL)
            {
                p->next[i]->Fail = root;
                Q.push(p->next[i]);
            }
        }
    
        while(Q.size())
        {
            p = Q.front();Q.pop();
    
            for(int i=0; i<MAXM; i++) if(p->next[i])
            {///如果节点p的next[i]不为空
    
                temp = p->Fail;///查找另一个最近的next[i]不为空的地方
    
                while(temp != NULL)
                {
                    if(temp->next[i] != NULL)
                    {///查找到
                        p->next[i]->Fail = temp->next[i];
                        break;
                    }
    
                    temp = temp->Fail;
                }
    
                if(temp == NULL)
                    p->next[i]->Fail = root;
    
                Q.push(p->next[i]);
            }
        }
    }
    void FreeTrie(Ac_Trie_Node *root)
    {///释放内存
        Ac_Trie_Node *p = root;
    
        for(int i=0; i<MAXM; i++)
        {
            if(p->next[i] != NULL)
                FreeTrie(p->next[i]);
        }
    
        free(p);
    }
    int Query(Ac_Trie_Node *root)
    {
        Ac_Trie_Node *p = root, *temp;
        int sum=0;
    
        for(int i=0; MumStr[i]; i++)
        {
            int k = MumStr[i]-'a';
    
            while(!p->next[k] && p != root)
                p = p->Fail;
    
            if(!p->next[k])continue;///根节点下面没有这个字母
    
            temp = p = p->next[k];
    
            while(temp != root && temp->leaf != -1)
            {///查找路径上的所有子节串,因为每个子串只出现一次,所以赋值为-1,防止重搜
                sum += temp->leaf;
                temp->leaf = -1;
                temp = temp->Fail;
            }
        }
    
        return sum;
    }
    
    int main()
    {
        int T;
    
        scanf("%d", &T);
    
        while(T--)
        {
            int M; char s[107];
            Ac_Trie_Node *root = new Ac_Trie_Node();
    
            scanf("%d", &M);
    
            while(M--)
            {
                scanf("%s", s);
                Insert(root, s);
            }
    
            GetFail(root);
    
            scanf("%s", MumStr);
            int ans = Query(root);
    
            printf("%d
    ", ans);
    
            FreeTrie(root);
        }
    
        return 0;
    }
  • 相关阅读:
    【bzoj1196】[HNOI2006]公路修建问题
    【bzoj1082】栅栏[SCOI2005]
    【bzoj1012】[JSOI2008]最大数maxnumber
    【bzoj2330】 [SCOI2011]糖果
    【bzoj1008】[HNOI2008]越狱
    【bzoj1002】 [FJOI2007]轮状病毒DP
    【bzoj1001】[BeiJing2006]狼抓兔子
    C++-POJ2234-Matches Game[Nim][SG函数]
    C++-POJ1067-取石子游戏
    lodash常用
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4750551.html
Copyright © 2011-2022 走看看