• 字符串——Trie


    Trie

    维护一个字符串集合,支持两种操作:
    I x 向集合中插入一个字符串 x;
    Q x 询问一个字符串在集合中出现了多少次。
    假设所有字符串长度之和为n,构建字典树的时间复杂度为O(n)
    假设要查找的字符串长度为k,查找的时间复杂度为O(k)
    拓展应用:
    1.一个字符串是集合中多少个字符串的前缀
    解法:每个节点都计数即可

    //Trie树快速存储字符集合和快速查询字符集合
    //支持大小写+数字
    #include
    using namespace std;
    const int N = 3000001;
    //son[][]存储子节点的位置,分支最多26条;
    //cnt[]存储以某节点结尾的字符串个数(同时也起标记作用)
    //idx表示当前要插入的节点是第几个,每创建一个节点值+1
    int son[N][65], cnt[N], idx;
    char str[N];
    int getnum(char x) {
        if (x >= 'A' && x <= 'Z')
            return x - 'A';
        else if (x >= 'a' && x <= 'z')
            return x - 'a' + 26;
        else
            return x - '0' + 52;
    }
    void insert(char* str)
    {
        int p = 0;  //类似指针,指向当前节点
        for (int i = 0; str[i]; i++)
        {
            int u =getnum(str[i]); //将字母转化为数字
            if (!son[p][u]) son[p][u] = ++idx;   //该节点不存在,创建节点
            p = son[p][u];  //使“p指针”指向下一个节点
            cnt[p]++;  //结束时的标记,也是记录以此节点结束的字符串个数(前缀)
        }// cnt[p]++出现次数
    }
    
    int query(char* str)
    {
        int p = 0;
        for (int i = 0; str[i]; i++)
        {
            int u = getnum(str[i]);
            if (!son[p][u]) return 0;  //该节点不存在,即该字符串不存在
            p = son[p][u];
        }
        return cnt[p];  //返回字符串出现的次数
    }
    
    int main()
    {
        int t; cin >> t;
        while (t--)
        {
            int n, m;
            cin >> n >> m;
            for (int i = 0; i <= idx; i++)
                for (int j = 0; j <= 64; j++)
                    son[i][j] = 0;
            for (int i = 0; i <= idx; i++)
                cnt[i] = 0;
            idx = 0;
            for (int i = 1; i <= n; i++)
            {
                cin >> str;
                insert(str);
            }
            for (int i = 1; i <= m; i++)
            {
                cin >> str;
                cout << query(str)<<endl;
            }
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
  • 相关阅读:
    简约商务报告PPT模板
    什么是代码签名证书?
    多线程可见
    Word文档里面如何给内容进行注释添加
    ES6之Symbol.isConcatSpreadable
    常见的设计模式
    第二章:Pythonocc官方demo 案例44(几何板条)
    QDebug 日志输出的浏览器
    5.1 Spring源码-读取不完整Bean的解决原理
    南京邮电大学电工电子(数电)实验报告——计数器 & 移位寄存器
  • 原文地址:https://blog.csdn.net/thexue/article/details/126074498