• KMP,Tire,高级并查集


    转自acwing

    tire

    int son[N][26], cnt[N], idx;
    // 0号点既是根节点,又是空节点
    // son[][]存储树中每个节点的子节点
    // cnt[]存储以每个节点结尾的单词数量
    
    // 插入一个字符串
    void insert(char *str)
    {
        int p = 0;
        for (int i = 0; str[i]; i ++ )
        {
            int u = str[i] - 'a';
            if (!son[p][u]) son[p][u] = ++ idx;
            p = son[p][u];
        }
        cnt[p] ++ ;
    }
    
    // 查询字符串出现的次数
    int query(char *str)
    {
        int p = 0;
        for (int i = 0; str[i]; i ++ )
        {
            int u = str[i] - 'a';
            if (!son[p][u]) return 0;
            p = son[p][u];
        }
        return cnt[p];
    }

    并查集

    (1)朴素并查集:
    
        int p[N]; //存储每个点的祖宗节点
    
        // 返回x的祖宗节点
        int find(int x)
        {
            if (p[x] != x) p[x] = find(p[x]);
            return p[x];
        }
    
        // 初始化,假定节点编号是1~n
        for (int i = 1; i <= n; i ++ ) p[i] = i;
    
        // 合并a和b所在的两个集合:
        p[find(a)] = find(b);
    
    
    (2)维护size的并查集:
    
        int p[N], size[N];
        //p[]存储每个点的祖宗节点, size[]只有祖宗节点的有意义,表示祖宗节点所在集合中的点的数量
    
        // 返回x的祖宗节点
        int find(int x)
        {
            if (p[x] != x) p[x] = find(p[x]);
            return p[x];
        }
    
        // 初始化,假定节点编号是1~n
        for (int i = 1; i <= n; i ++ )
        {
            p[i] = i;
            size[i] = 1;
        }
    
        // 合并a和b所在的两个集合:
        size[find(b)] += size[find(a)];
        p[find(a)] = find(b);
    
    
    (3)维护到祖宗节点距离的并查集:
    
        int p[N], d[N];
        //p[]存储每个点的祖宗节点, d[x]存储x到p[x]的距离
    
        // 返回x的祖宗节点
        int find(int x)
        {
            if (p[x] != x)
            {
                int u = find(p[x]);
                d[x] += d[p[x]];
                p[x] = u;
            }
            return p[x];
        }
    
        // 初始化,假定节点编号是1~n
        for (int i = 1; i <= n; i ++ )
        {
            p[i] = i;
            d[i] = 0;
        }
    
        // 合并a和b所在的两个集合:
        p[find(a)] = find(b);
        d[find(a)] = distance; // 根据具体问题,初始化find(a)的偏移量
    堆 —— 模板题 AcWing 838. 堆排序, AcWing 839. 模拟堆
    // h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
    // ph[k]存储第k个插入的点在堆中的位置
    // hp[k]存储堆中下标是k的点是第几个插入的
    int h[N], ph[N], hp[N], size;
    
    // 交换两个点,及其映射关系
    void heap_swap(int a, int b)
    {
        swap(ph[hp[a]],ph[hp[b]]);
        swap(hp[a], hp[b]);
        swap(h[a], h[b]);
    }
    
    void down(int u)
    {
        int t = u;
        if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2;
        if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        if (u != t)
        {
            heap_swap(u, t);
            down(t);
        }
    }
    
    void up(int u)
    {
        while (u / 2 && h[u] < h[u / 2])
        {
            heap_swap(u, u / 2);
            u >>= 1;
        }
    }
    
    // O(n)建堆
    for (int i = n / 2; i; i -- ) down(i);

    KMP

    // s[]是长文本,p[]是模式串,n是s的长度,m是p的长度
    求模式串的Next数组:
    for (int i = 2, j = 0; i <= m; i ++ )
    {
        while (j && p[i] != p[j + 1]) j = ne[j];
        if (p[i] == p[j + 1]) j ++ ;
        ne[i] = j;
    }
    
    // 匹配
    for (int i = 1, j = 0; i <= n; i ++ )
    {
        while (j && s[i] != p[j + 1]) j = ne[j];
        if (s[i] == p[j + 1]) j ++ ;
        if (j == m)
        {
            j = ne[j];
            // 匹配成功后的逻辑
        }
    }


  • 相关阅读:
    CLASS 类 __getattr__
    class多态
    class类 __repr__ 与__str__
    CLASS类继承
    calss 类
    SVN报错:database is locked
    项目:表格打印(字符图网格进阶、rjust、列表中最长的字符串长度)
    项目:口令保管箱,批处理文件配置.bat
    字典方法 setdefault()、pprint;迭代、递归的区别
    项目:在wiki标记中添加无序列表(split、join巩固)
  • 原文地址:https://www.cnblogs.com/cyq123/p/12904686.html
Copyright © 2020-2023  润新知