zoukankan      html  css  js  c++  java
  • SAM练习记录

    SAM练习记录

    洛谷 P1368 工艺

    其实是最小表示法裸题

    倍长后建SAM跑最小的边走|S|步即可

    Code


    CF 235 C. Cyclical Quest

    对主串建SAM

    然后每个串倍长,跑的时候维护一下匹配长度再更新答案,还有判断一个节点是否重复到达。

    Code


    BZOJ1396: 识别子串

    一开始写这个题的时候固执的认为是线段树合并..

    显然出现次数为1的串的rigit集合大小为1,我们直接处理一下就好了,设Ta和Ta父亲的长度是(len_x)(len_p)

    那么在区间([len_x-len_p,len_x])的都可以取(len_p+1),而在([1,len_x-len_p+1])的都可以取(len_x+1-i)

    分开放到两个线段树维护一下就可以了,也可以离线(O(n))

    Code


    BZOJ2555: SubString

    lct维护SAM裸题

    动态维护par树并且维护一下子树大小就可以了

    注意维护子树大小时link的时候x,y都要保证fa是0,wa了好久

    Code


    「TJOI / HEOI2016」字符串

    注意读题,一个是子串一个没有子串...

    sam可以求最长公共后缀,所以先把串反过来。

    考虑二分答案,每次从(d)在SAM上的那个点倍增向上跳,找到最短的那个大于当前答案的点,查询它的rigit集合是否在([a+mid-1,b])区间,可以用线段树合并(可持久化线段树?)维护

    Code


    「NOI2018」你的名字

    68分:考虑统计两个串的本质不同公共子串个数。

    方法:对S,T同时建SAM,然后在S的SAM上跑T这个串,可以得到T的每个(i)为末尾的串的在S中的匹配长度,然后把这个长度表示打到T的对应节点上面去,最后对T的par树跑一遍传一传标记。

    Code:

    100分:其实和68差不多

    对S的SAM用线段树合并之类的维护一下right集合,然后每次还是跑匹配,并把标记打到T上去。

    考虑到维护匹配长度,显然par树越上,right集合越大,我们可以查询right集合在不在区间里面。于是考虑二分一个匹配长度,然后倍增跳到对应节点,再线段树检测一下合不合法。

    但仔细想一想这个过程,发现是可以直接暴力跳par树的,因为我们得满足势能嘛,就变成一个(log)的了

    跳的时候注意一下细节,我看大家写的都不咋一样,就不具体说了。

    Code

  • 相关阅读:
    feign远程调用问题
    java8--stream
    feign业务组件远程请求 /oauth/token
    redis实现自增序列
    MySQL数据库 相关知识点
    netty
    spring的启动流程及bean的生命周期
    MethodHandleVS反射
    并发与并行
    关于注解的思考
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10534937.html
Copyright © 2011-2022 走看看