zoukankan      html  css  js  c++  java
  • Ideas and Tricks Part III

    58.$SAM$后缀自动机

    东西挺多的

    $SAM$中每一个节点都是一个$endpos$的等价类,节点与节点之间有字符的转移。构成的$SAM$是一个$DAG$,每一个在原串中本质不同的子串都唯一对应一条在$SAM$从初始节点出发的路径

    可以发现对于一个节点的那些串,如果以长度升序排序后,前一个串是后一个串的后缀并且长度相差$1$,那么记最长的那一个串长度为$len(x)$,最短的一个串为$minlen(x)$,定义后缀链接为这个串最长一个串的$endpos$不和当前节点的$endpos$集合相同的节点,那么可以发现$len(link(x))=minlen(x)$,那么可以知道一个点所包含的本质不同子串个数就是$len(x)-len(link(x))$

    首先是其构造,大概流程就是,在构造过程中记录前面一个前缀的节点,在后面添加一个字符的时候,新建一个节点$x$,先不断地扩展那些没有当前字符转移的节点,把这些节点的这种字符转移转移到当前节点$x$上,设第一个以前就有这种字符转移的节点为$p$,转移到的节点为$q$,如果$len(q)=len(p)+1$,那么直接把x的后缀链接设为$q$,否则克隆出一个新节点$cl$,令$len(cl)=len(p)+1$并且把所有小于其长度的节点重定向为$cl$,最后把$q$和$x$连接到$cl$上

    可以发现$link(x)$形成了一个树形结构,那么这棵树就叫$parent$树,这棵树有很多性质

    如果设那些前缀节点为终点,那么终点的$endpos$集合就是对应前缀的下标,那么对于任意一个节点来说,其$endpos$集合就是这个节点在$parent$树上子树所有终点构成的集合,那么可以方便通过一次$dfs$维护出所有节点$endpos$集合的大小,对于具体位置是哪些需要线段树合并来做

    对于$parent$树上节点$x$,那么节点$x$到根路径上所有节点对应字符串恰好构成了所有$x$节点的后缀,相当于划分成了若干个区间,并且这些区间不交

    那么在$parent$树上跳类似于$AC$自动机上建出的失配树上跳,只不过$SAM$相当于把所有子串建出了一个压缩版的$AC$自动机,那么这个东西可以做类似求两个串最长公共子串的问题,就是不断尝试去匹配,如果匹配失败就跳$parent$树,直到跳到空节点或者重新匹配上

    《各 种 套 路》

    59.最小圆覆盖

    随机增量法,随机增量法就是对于前$i$个元素,处理出来符合条件的答案,然后试图去扩展到$i+1$个位置,需要保证原来的序列是打乱过的

    最小圆覆盖就是这个的应用

    考虑当前扩展到第$i$个点,设当前圆为$O$,那么去判断一下$i+1$是否在$O$内,如果在那么继续下一轮判断,如果不在,那么说明$i+1$这个点一定在新的覆盖圆上,因为这个圆需要向$i+1$这个点偏移,但又同时要满足原来的点在圆内,之前已经是最小覆盖圆,有至少一个点在圆上,如果$i+1$不在圆上,那么这个圆一定可以继续缩小

    那么现在可以先把圆心设为这个点,半径为$0$,然后重新枚举之前的点,看是否在圆上,如果不在把圆设为过这两个点的圆,然后继续枚举前面的点,如果还不在圆上,把圆设为经过这三个点的圆,那么不断做下去就可以找到最小覆盖圆

    每一次进入下一层循环的概率都是对应下标分之$3$,那么最终期望运行复杂度为$O(n)$

    60.竞赛图求哈密顿回路

    竞赛图就是无向完全图给每条边定一个方向,在任意一个竞赛图中一定存在一条哈密顿路径,在一个强连通的竞赛图中一定存在一条哈密顿回路

    对于求哈密顿路径,可以如下的归纳构造

    对于$1$到$i-1$的点,我们假设已经求得其哈密顿路径

    如果当前i号点有连向$1$号点或者$i-1$号点连向了$i$号点,那么直接加入路径的首或者尾

    否则记$x$号点为$i$第一个连向的节点,那么$[1,x)$中的节点,都是连向$i$的,那么可以构造$...(x-1) ightarrow i ightarrow x ightarrow (x+1)...$的路径

    求得哈密顿路径之后就可以构造哈密顿回路,那么首先找出最后一个有边连向第一个节点的点

    考虑还是归纳构造,对于$1$到$i-1$的点已经构造出其哈密顿回路,也就是一个环

    分两种情况讨论,首先如果没有边连向环中,那么先跳过这个节点,向下考虑

    那么设第一个环中的节点$x$,使得$i$连向$x$,那么可以构造一个新环,就是将所有当前不在环中的点,依次插入$x$前面

    61.对于询问区间定长设关键点

    如果每一次询问的区间都是相同长度的,设长度都为$k$,那么可以在原序列上每隔$k$个点设一个关键点,然后在关键点上记录这个点向后$k$个的后缀信息,向前$k$个的前缀信息,那么每一次询问的区间一定覆盖了某一个关键点,那么利用关键点的信息即可

    62.点减边

    对于树上路径问题,如果考虑重链剖分的话,会把某一条路径拆成$log$个区间,对于那些某一条路径只计一次数的问题,如果对于每一个区间都进行一次统计的话会算重,那么可以考虑统计是区间内的点和边的数量

    然后最后统计答案的时候相减,只会得到$0/1$的答案,还有注意在重链剖分的时候,需要将每一条链顶上面的那条轻边算到这条链上来

    具体问题具体分析

    63.解二维递推式

    列出计数$DP$后,如果是二维形式,并且数据范围给的是$O(n)$级别的话,考虑去解其递归式

    一般需要再列出一个方程,与之前的方程联立,得到一阶递推关系,然后去做

  • 相关阅读:
    解决execjs 调用js 问题
    处理 get请求套字典问题
    js2py js逆向
    前端页面自适应
    newspaper抓新闻
    easygui
    pycharm 安装插件
    scrapy_代理使用
    SQLAlchemy 介绍,建表,及表的操作 (增 删 改 查)
    数据分析之pandas模块下
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/14170713.html
Copyright © 2011-2022 走看看