人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的理论似懂非懂.然后看了下自动机的构造发现代码倒是挺简单,但是理解原理却是十分的困难,最后在网上找到一篇带例子的讲解帖子,我感觉算是能够说服我的吧放个链接: http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html 本题也是CLJ论文里的题,关键是如何求…
建后缀自动机 然后统计次数,只需要算出right集合的大小即可, 然后更新f[l[i]]和rit[i]取个max 然后根据rit集合短的一定包含长的的性质,从后往前更新一遍即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i)…
传送门 解题思路 首先建出\(sam\),然后把\(siz\)集合通过拓扑排序算出来.对于每个点只更新它的\(maxlen\),然后再从大到小\(dp\)一次就行了.因为\(f[maxlen-1]>=f[maxlen]\)这个性质. 代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int MAXN =…
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 后缀自动机的水好深啊!懂不了相关证明,带着结论把这个题做了.看来这滩深水要以后再来了. 本题要用到一个叫 Right[P] 的数组,表示 P对应的子串在原串中出现的所有位置的末尾位置下标的集合.本题中,用这个数组存储集合大小就好了,即 P对应的子串在原串中出现了Right[p]次. 而Right[P]的值,等于从改点出发到结束状态的方案数.但这个不好求,而是要用到另一个求法:用 Parent树: (暂时由…
Substrings \[ Time Limit: 100ms\quad Memory Limit: 1572864 kB \] 题意 给出一个长度为 \(250000\) 的字符串,求出所有 \(x\) 的 \(F(x)\) . \(F(x)\) 含义为长度为 \(x\) 的子串出现的最多次数. 思路 先对给出的串构建后缀自动机,设 \(dp[i]\) 为后缀自动机上节点 \(i\) 包含的最长子串的出现的次数.那么对于主链的上的点,可以直接赋初始值 \(dp[i] = 1\),也就是从根节点…
spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于一个节点s,它的长度范围是[Min(s),Max(s)],同时他的出现次数是|Right(s)|.那么我们用|Right(s)|去更新F(Max(s))的值.那么现在的问题是如何快速求 |right(s)| 了还记得论文里parent tree吗?看看那个就知道了,不懂可以留言.接下来还有一步,我们…
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string 'ababa' F(3) will be 2 because there is a string 'aba…
题目大意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.F(1)..F(Length(S)) 建出SAM, 然后求出Right, 求Right可以按拓扑序dp..Right就是某个点到结束状态的路径数, parent树上last的那一条链都是结束状态...然后用Right去更新答案.. spoj卡常数..一开始用DFS就炸了, 改用BFS就A了.. (贴一下丽洁姐的题解: 我们构造S的SAM,那么对于一个节点s,它的长度范围是[Min(s),Max(s)],同时他的出…
讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 2000000 #define N 30 #define ll l…
题意: 求多个串<=10的最长连续子串 一个串建SAM,然后其他串在上面走 每个状态记录所有串在这个状态的公共子串的最小值 一个串在上面走的时候记录与每个状态公共子串的最大值,注意出现次数向父亲传递,一个状态能到达说明了Suffix Link指向的状态可以取到最大子串,这一步对val后基数排序然后倒着更新就行了 注意两点: 1.空间要开两倍,基数排序用的东西也要两倍哦 2.答案不能用mn[1]更新!!!!因为mn[1]没有意义啊root状态一个子串也没有还可能有某些bug #include <…