zoukankan      html  css  js  c++  java
  • Sam小结和模板

    Sam 的一些总结

    注意在子串在某个节点的性质,其 father 上也会有相同的性质

    1. 统计子串出现的次数

    • (parent) 树上做 (dp),对于每一个节点,初始化为 (dp[i] = 1),然后 (dp[father] = sum dp[son])

    2. 子串的个数

    • 利用后缀数组,(sum_{i=2}^{n} len-sa[i]+1-height[i]) 就是答案
    • 利用后缀自动机,(dp[i]) 表示第 (i) 个节点拥有的字符串个数,可以让 (v in u'next)(dp[u] = sum dp[v]),最后的 (dp[1]-1) 就是答案。
    • 利用后缀自动机,(sum_{i=2}^{sz} node[i].len - node[father].len) 就是答案。

    3. 子串出现的最左和最后位置

    • 在构建后缀自动机的时候,令 (left[np] = right[np] = id),如此可以求出最左位置。
    • (parent) 树上跑,(right[father] = max(right[father], right[son])),如此可以求出最右位置。

    4. 求 LCS

    • 每次匹配的的时候看当前匹配的时候 (p) 有没有往一条 (char) 的边,没有的话往 (fa[p]),如果一直跳到 (p=0),就重新赋值 (p=1,res=0),否则就往 (node[p][char]) 跳,并让 (res++)
    • 求多个字符串的时候,就要考虑往 (father) 上的更新。

    5. 求字典序第 k 小

    • (dfs) 出每个节点往后有多少子串,然后从小到大在 (dfs) 一边找到第 (k) 大。
    • 如果 (v) 往后的字符串比 (k) 小,那么直接 (k-cnt[v])
    • 否则往下走一步,并让 (k-)(-)

    6. Sam 上的基数排序

     for(int i=0; i<=sz; i++)    tax[i] = 0;
     for(int i=1; i<=sz; i++)    tax[step[i]]++;
     for(int i=1; i<=sz; i++)    tax[i] += tax[i-1];
     for(int i=1; i<=sz; i++)    gid[tax[step[i]]--] = i;
    

    7. Sam模板

    struct Sam {
        int node[maxn<<1][27], fa[maxn<<1], step[maxn<<1];
        int sz, last;
        int newnode() {
            mes(node[++sz], 0);
            fa[sz] = step[sz] = 0;
            return sz;
        }
        void init() {
            sz = 0;
            last = newnode();
        }
        void insert(int k) {
            int p = last, np = last = newnode();
            step[np] = step[p]+1;
            for(; p&&!node[p][k]; p=fa[p])
                node[p][k] = np;
            if(p==0) {
                fa[np] = 1;
            } else {
                int q = node[p][k];
                if(step[q] == step[p]+1) {
                    fa[np] = q;
                } else {
                    int nq = ++sz;
                    memcpy(node[nq], node[q], sizeof(node[q]));
                    fa[nq] = fa[q];
                    step[nq] = step[p]+1;
                    fa[np] = fa[q] = nq;
                    for(; p&&node[p][k]==q; p=fa[p])
                        node[p][k] = nq;
                }
            }
        }
    } sam;
    
  • 相关阅读:
    OpenStack Pike超详细搭建安装文档 LinuxBridge版
    OpenStack Ocata 超详细搭建文档
    此博客关闭,转到 https://www.justbio.wang/
    面向对象03 封装 反射 内置方法
    面向对象02 继承
    面向对象01
    awk使用说明
    MySQL优化聊两句
    Redis分布式集群几点说道
    Nginx最大客户连接数算法一些遐想
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/10987468.html
Copyright © 2011-2022 走看看