字典树Trie的简单题目

题意:给N个模式串,每个不超过个字符,再给M个句子,句子长度< 100 判断每个句子里是否包含模式串 N < 10, M < 10 ,字符都是小写字母
5 8
abcde
defg
cdke
ab
abcdkef
abkef
bcd
bca
add
ab
qab
f

#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#define letters 26
#include<cstring>
int nNodesCount=0;
struct CNode
{
    CNode *pChilds[letters];
    CNode *pPrev; //前缀指针
    bool bBadNode; //查看是否是危险节点
    void Init()
    {
       memset(pChilds,0,sizeof(pChilds));
       bBadNode=false;
       pPrev=NULL;
    }
};
CNode Tree[200]; //10个模式串,每个10个字符,每个字符一个节点, 也只要100个节点
void Insert(CNode *pRoot,char *s)
{
    //将模式串s插入trie树
    for (int i=0;s[i];i++)
    {
        if (pRoot->pChilds[s[i]-'a']==NULL)
        {
            pRoot->pChilds[s[i]-'a']=Tree+nNodesCount;
            nNodesCount++;
        }
        pRoot=pRoot-pChilds[s[i]-'a'];
    }
    pRoot->bBadNode=true;
}
void BuildDfa()
{
    //在trie树上加前缀指针
    for (int i=0;i<letters;i++)
        Tree[0]->pChilds[i]=Tree+1;
    Tree[0].pPrev=NULL;
    Tree[1].pPrev=Tree;
    deque<CNode *>q;
    q.push_back(Tree+1);
    while (!q.empty())
    {
        CNode *pRoot=q.front();
        q.pop_front();
        for (int i=0;i<letters;i++)
        {
            CNode *p=pRoot->pChilds[i];
            if (p)
            {
                CNode *pPrev=pRoot->pPrev;
                while (pPrev)
                {
                    if (pPrev->pChilds[i])
                    {
                        p->pPrev=pPrev->pChilds[i];
                        if (p->pPrev->bBadNode)
                            p->bBadNode=true; //自己的pPrev指向的节点是危险节点 则自己也是危险节点
                        break;
                    }
                    else
                        pPrev=pPrev->pPrev;
                }
                q.push_back(p);
            }
        }
    }
}

bool SearchDfa(char *s)
{
    //返回值为true则说明包含模式串
    CNode *p=Tree+1;
    for (int i=0;s[i];i++)
    {
        while (true)
        {
            if (p->pChilds[s[i]-'a'])
            {
                p=p->pChilds[s[i]-'a'];
                if (p->bBadNode)
                    return true;
                break;
            }
            else
                p=p->pPrev;
        }
    }
}
int main()
{
    nNodesCount=2;
    int M,N;
    cin>>N>>M;
    for (int i=0;i<N;i++)
    {
        char s[20];
        cin>>s;
        Insert(Tree+1,s);
    }
    BuildDfa();
    for (int i=0;i<M;i++)
    {
        char s[200];
        cin>>s;
        cout<<SearchDfa(s)<<endl;
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/Nishadiaoma/article/details/52234816
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞