• 「考试总结」2021-01-25 口胡


    T1

    首先有"本质不同的回文串的数量级是 (O(n)) 的"

    证明很简单,考虑sam上最多有 (2n-1) 个节点,同时这些节点中每个最多有一个回文串

    (如果有多个的话,那么短串的 (endpos) 比长串要多)

    其实在这个题目里面关注的是 (midpos),那么给所有的回文串标号

    (manacher) 处理所有的回文中心,把短串向长串连边得到一个树

    对于每次处理的 (id[i-r[i]+1,i+r[i]-1]) 异或上 (i) 最后按照 (SAM) 维护 (endpos) 个数那样维护 (midpos) 的异或和即可

    一开始想的是倍增后缀树的做法,其实和正解是一致的,考完了之后优化了一下思路写了出来

    所以以后要注意的是难题口胡完了要写

    复杂度 (Theta(n))

    注意的几个点:

    (1.) 手写 (hash)

    (2.) 字符串清空一定要手动清全,因为 (t[i]) 后面的遗留可能对计算造成影响

    (3.) 森林的根节点的 (res[x]) 不能取最大值

    T2

    子串排名递减,总和增加,所以两者交点最多有一个,二分统计即可

    但是考试的时候不会如何求排名,所以 (SAM) 维护子串排名方式如下:

    每个后缀树上的点维护的是一个后缀,那么我们翻转之后就能得到前缀

    先算 (endpos) 大小表示这个点一共多少个串

    然后把所有的出边都标号,标号就是 (s[pos[x]+len[fa[x]]])

    这样每个点在后缀树上排序之后再 (dfs) 得到每个点的 (rk)

    对于每个 ([l,r]) 倍增出来对应的点之后直接 (rk[now]+len[now]-(r-l+1)+1) 即可

    T3

    后缀自动机板子题,不过考试的过程中发现 (dfs) 会本地爆栈,浪费了很多时间回忆如何写基数排序,如下:

    for(reg int i=1;i<=tot;++i) ton[len[i]]++; 
            for(reg int i=1;i<=slen;++i) ton[i]+=ton[i-1]; 
            for(reg int i=tot;i>=1;--i) id[ton[len[i]]--]=i;
            for(reg int i=tot;i>=1;--i){
                if(sz[id[i]]>1) ans=max(ans,1ll*sz[id[i]]*len[id[i]]); 
                sz[fa[id[i]]]+=sz[id[i]];
            } printf("%lld
    ",ans);
    

    端正态度,加速思考

  • 相关阅读:
    通过应用程序域AppDomain加载和卸载程序集(转自张逸)
    Asp.net 2.0 中获取控件输出的Html代码 (转)
    工作和学习
    查询数据库中的所有表
    观活动板房感怀
    温心之旅
    读书无用论是21世纪最大的阴谋
    我渴望女人,但我更渴望成功
    外面比家里亮
    近来,可好?
  • 原文地址:https://www.cnblogs.com/yspm/p/14324423.html
Copyright © 2020-2023  润新知