后缀自动机
Clove_unique
All that you have lost can be won back bit by bit as long as you wish for it.
展开
-
[SPOJ8222]NSUBSTR - Substrings(后缀自动机)
题目描述传送门 题意:定义f(i)为长度为i的子串的最多出现次数(可重复),求f(1…n)题解很显然f(1..n)不升,那么可以用f(i)=max{f(i),f(i+1)} right集合表示当前状态在哪里出现过,其实就是求right集合的大小 主链上的所有的点right集合初始为1(因为它代表了原串的一个前缀) 如果两个点的right集合有交集,那么一定一个是另一个的真子集 所以在par原创 2016-12-30 08:33:31 · 892 阅读 · 0 评论 -
[BZOJ4698][Sdoi2008]Sandy的卡片(后缀数组+st表||后缀自动机)
题目描述传送门题目大意:给出n个长度为mi的串,求趋势相同的最长公共子串题解将前后两个数差分之后就是一个裸的最长公共子串问题了 将所有的串怼在一起求sa和height,然后用一个指针扫出来至少含有n个串的代码#include#include#include#include#includeusing namespace std;#define N 20000原创 2017-04-16 21:44:23 · 811 阅读 · 0 评论 -
[BZOJ4516][Sdoi2016]生成魔咒(后缀数组+链表||后缀自动机)
题目描述传送门题解题意实际上是求对于每一个前缀本质不同的子串个数 那么可以转化为对于每一个前缀只求包含最后一个点的和前面不重复的子串个数,然后将答案累加 把串反过来建后缀数组 然后实际上就是对于每一个后缀求与其它后缀不重复的前缀个数,也即是后缀长度减去height值 但是需要注意的一点是要排除在其后面的后缀的干扰 那么可以倒序求解,求解之后将这个后缀删除,height不升,可以用链表维护一原创 2016-12-28 18:38:57 · 1015 阅读 · 0 评论 -
[BZOJ2555]SubString(后缀自动机+lct)
题目描述传送门题解询问每一个字符串出现过几次,实际上就是将这个字符串在后缀自动机上匹配,然后查询最终匹配到的那个点的right集合的大小 又因为是在线的,pre指针经常会变化,所以把pa树用lct维护一下 维护lct的时候不要维护子树和,而应该连上一个点就将它一直到根的路径上的点都加上这个点的权,断开一个点就减去这个点的权,这样维护一棵有根树代码#include<algorithm>#incl原创 2017-04-04 08:42:00 · 898 阅读 · 0 评论 -
[BZOJ2806][Ctsc2012]Cheat(广义后缀自动机+dp)
题目描述传送门题解hxy神犇出过一次胡策题,hxy神犇后缀自动机太神了没办法只能%%%@hxy首先对所有的模板串建立广义后缀自动机,然后对于每一个查询的串,预处理出来这个点最多向前多长是“熟悉的”,也就是以它为结尾的后缀在模板串中出现的最长的是多少a(i) 然后就是dp了,首席二分答案L,令f(i)表示到第i位,合法的划分方案中“熟悉的”总长度,最后只需要判断f(n)是否>=n*0.9 dp方程原创 2017-03-30 17:15:40 · 782 阅读 · 0 评论 -
[BZOJ3238][Ahoi2013]差异(后缀数组+单调栈||后缀自动机+树形dp)
题目描述传送门题解这道题实际上还是非常有趣的。 首先根据题目的描述答案应该为所有后缀的组合长度再减去两两的lcp 首先算出来总和 求出sa和height,用两次单调栈可以求出来以某一个点的height为最小值的最长区间 可以发现以这个点为分界点,区间的左右两边两两组合最小值一定是当前点的height,也就是lcp的长度 然后再计算答案就可以了代码#include<iostream>#in原创 2016-12-28 10:00:50 · 818 阅读 · 0 评论 -
[BZOJ2780][Spoj8093]Sevenk Love Oimaster(广义后缀自动机)
题目描述传送门题解对于所有的模板串建立广义后缀自动机,对于每一个点统计一下right集合中有几个模板串 然后对于所有的查询串在后缀自动机上匹配,然后看一下最终匹配到的那个点有几个模板串就行了 具体的方法是记录一下每一个点最后匹配到的是哪个模板串,然后记录一个cnt,每一次暴力顺着pre指针往上跳,跳到已经更新过的就退出 时间复杂度不大好算,其实就是每一次加入一个串自动机上的点最多被遍历一次代码原创 2017-03-30 11:40:08 · 1288 阅读 · 0 评论 -
[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)
题目描述传送门题解只与一个空地相邻的空地就是指叶子节点,刚开始理解错了 对于每一个叶子节点以它为根然后对这棵树建立广义后缀自动机 然后对于后缀自动机上的每一个点,以这个点为结尾的不相同的字符串其实就是step(i)-step(pre(i))个,也就是合法的区间长度 因为同一个字符串不会跑到不同的点上去啊…代码#include<algorithm>#include<iostream>#inc原创 2017-03-30 11:34:12 · 734 阅读 · 0 评论 -
[BZOJ4566][Haoi2016]找相同字符(后缀自动机)
题目描述传送门题解将两个串接在一起建立后缀自动机,中间加一个分隔符 对于自动机上的每一个点,统计其right集合中在第一个串中的数量cnt1,在第二个串中的数量cnt2 对于某一个点合法的长度是[step(pre(i))+1,step(i)] 答案累加就是cnt1*cnt2*(step(i)-step(pre(i)))代码#include<algorithm>#include<iostrea原创 2017-03-30 07:44:43 · 859 阅读 · 0 评论 -
[BZOJ2946][Poi2000]公共串(后缀自动机)
题目描述传送门题解同spoj1812代码#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define N 100005char s[N];int T,inf,n,p,np,q,nq,last,root,sz,ans;int ch[N][30],pre[N],step[N],c[N],pt[N]原创 2017-03-29 21:55:19 · 635 阅读 · 0 评论 -
[BZOJ1396]识别子串(后缀自动机+线段树)
题目描述传送门题解这题思路还是比较好想的 建立后缀自动机了之后统计每一个点right集合的大小,若一个点right集合的大小为1,那么以这个点为右端点的合法子串都是只在字符串中出现过一遍的,所谓合法就是长度在这个点的长度区间[Min,Max]里,这个点在原串中的位置也就是step 那么如何求每一个位置的最小值呢? 假设某一个点right集合大小为1,右端点为step,合法的长度区间为[Min,原创 2017-03-29 21:37:09 · 640 阅读 · 0 评论 -
[POJ1743]Musical Theme(后缀数组||后缀自动机)
题目描述传送门题解用height搞事情。。。 某个子串一定是一个后缀的前缀。 两个后缀的最长公共前缀是在 height 数组上的区间最小值。 先二分答案,把题目变成判定性问题:判断是否存在两个长度为mid的子串是相同的,且不重叠。把排序后的后缀分成若干组,其中每组的后缀之间的 height 值都不小于 k 。有希望成为最长公共前缀不小于 k 的两个后缀一定在同一组。 然后对于每组后缀,只须判断原创 2016-12-26 11:21:07 · 1330 阅读 · 2 评论 -
[SPOJ7258]SUBLEX - Lexicographical Substring Search(后缀自动机)
题目描述传送门题解明明是sa的题嘛,可是为了练习sam用sam来写 sam从根到每一个点的路径都构成了一个子串,并且这些子串都是本质互不相同的 所以我们可以用拓扑序或者dfs统计一遍当前节点再往后走会有多少个不同的子串 然后询问的时候暴力枚举每一个点的每一个儿子然后找第k个就行了代码#include<iostream>#include<cstring>#include<cstdio>us原创 2016-12-30 10:04:14 · 680 阅读 · 0 评论 -
[SPOJ1811]LCS - Longest Common Substring(后缀自动机)
题目描述传送门 题意:给出两个串,求最长公共子序列。题解后缀自动机第一题。 首先对第一个串建立sam,然后让第二个串在sam上暴力匹配,匹配不到就蹦到它的pre指针。匹配上的子串最长长度就是最长公共子序列。代码#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define N 500005cha原创 2016-12-29 20:53:42 · 883 阅读 · 0 评论 -
[SPOJ1812]LCS2 - Longest Common Substring II(后缀自动机)
题目描述传送门 题意:给出若干串,求最长公共子串。题解首先对于第一个串构建sam 对于某一个状态s,如果除第一个串之外的串匹配到此所得的最长长度是a1,a2,a3...an−1a_1,a_2,a_3...a_{n-1},那么这个状态的最长公共子串应为Min{a1,a2,a3...an−1,Max(s)}Min\{a_1,a_2,a_3...a_{n-1},Max(s)\} 同样,如果当前点被匹原创 2016-12-29 21:30:59 · 878 阅读 · 0 评论 -
[BZOJ2882]工艺(后缀自动机+stl||最小表示法)
题目描述传送门题解把串重复一遍然后建立后缀自动机 从头找一个最小的输出就行了 注意字符集非常大需要用map,然后可以用一个迭代器来找其实这道题正确的姿势应该是最小表示法 具体的可以看WC2003周源的课件代码#include<iostream>#include<cstring>#include<cstdio>#include<map>using namespace std;#defi原创 2017-01-01 11:33:00 · 807 阅读 · 0 评论 -
[BZOJ3998][TJOI2015]弦论(后缀自动机)
题目描述传送门题解还是要统计每一个点往后走能有多少个不同的子串。 如果T=0的时候就是主链上的点都是1,然后在parent树上把儿子加到父亲上去 如果T=1的是候则需要计算每一个点right集合的大小 最后在自动机上暴力找第k小的然后输出即可代码#include<iostream>#include<cstring>#include<cstdio>using namespace std;原创 2017-01-01 11:26:08 · 778 阅读 · 0 评论 -
[BZOJ4545]DQS的trie(广义后缀自动机+lct)
题目描述传送门题目大意: 先给出一棵trie,然后支持几种操作 若opt=1,则是一组询问,询问当前trie的本质不同的子串数目是多少。 若opt=2,则后面跟两个整数rt,si,表示以点rt为根向下长出一个子树,大小为si。即加入一个子trie 若opt=3,则是一组询问,后面输入一个字符串S,询问字符串S在当前trie中的出现次数。 题解这题其实是substring和生成魔咒的结合版原创 2017-05-04 21:08:23 · 1166 阅读 · 0 评论