Trie树(字典树)-题解 P2580 【于是他错误的点名开始了】

此题可以用STL中的map做,但是了解一下Trie树这个数据结构也是必须的。

Trie树(又称字典树)有以下特点:

  1. 根节点不包含字符,除它之外的每一个节点都包含一个字符。

  2. 从根节点到某一节点,路径上经过所有字符连起来为该节点对应字符串

  3. 每个节点的子节点包含字符不同,也就意味着字符是可以公用的

于是我们用这样一个结构体表示每一个节点:

在本题中可以用动态数组vector贮存每个子节点

         struct node{
            char c;//该点对应字符
            vector<struct node*>s;//储存儿子
            int tag;//标记是否为某一字符串结尾
            int rep; //应题目要求判断是否重复
           }*root=new struct node;

当然字典树有两个函数必不可少,分别是add(插入)和query(查询)。
具体怎么实现还看代码:

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <vector>
    #include <string>
    using namespace std;
    struct node{
        char c;
        vector<struct node*>s;
        int tag;
        int rep; 
    }*root=new struct node;
    void add(string str)
    {
        struct node*p=root;
        for(int i=0;i<str.length();i++)
        {
            int j;
            for(j=0;j<p->s.size();j++)
              if(p->s[j]->c==str[i])break;//如果找到对应公用字符
            if(j==p->s.size())//如果遍历完后没找到新建一个
            {
                struct node *newnode =new struct node;
                newnode->c=str[i];
                newnode->s.clear();
                newnode->tag=0;
                newnode->rep=0; 
                p->s.push_back(newnode);
                p=newnode;
            }
            else p=p->s[j];
        } 
        p->tag=1;//标志此节点为一字符串结尾
    }
    int query(string str)
    {
        struct node*p=root;
        for(int i=0;i<str.length();i++)
        {
            int j;
            for(j=0;j<p->s.size();j++)  
                if(p->s[j]->c==str[i]) 
                     {break;}
            if(j==p->s.size()) //如果遍历完后没找到
               return 0;
            p=p->s[j];
        }
        if(p->rep!=3)
        {
            p->rep=3;return p->tag;//找到的字符可能只是某一前缀而非整个字符串,所以需要一个tag标记
        }
        else if(p->rep==3)return p->rep;
    }
    int main()
    {
        int n,m;
        char tag[50];
        cin>>n;
        root->s.clear();
        for(int i=1;i<=n;i++)
        {
            string str;
            cin>>str;
            add(str);
        }
        cin>>m;
        for(int i=1;i<=m;i++)
        {
            string str;
            cin>>str;
            int flag=query(str);
            if(flag==0)puts("WRONG");
            else if(flag==1)puts("OK");
            else if(flag==3)puts("REPEAT");
        }
        return 0;
}
原文地址:https://www.cnblogs.com/Rye-Catcher/p/8478889.html