
字符串-后缀
Endless_Way
这个作者很懒,什么都没留下…
展开
-
POJ 3261 Milk Patterns
题意:给出一个字符串,问最长的可重叠的出现K次的子串的长度子串重复,考虑用到后缀数组、LCP(最长公共前缀)。二分答案,每一次按照子串排名依次遍历,看是否存在连续K个子串的height值均超过二分结果。代码应该是挺简洁的→_→#include<cstdio>#include<algorithm> #include<cstring>#define MAXN 20005#define MAX 1原创 2016-08-01 09:47:06 · 301 阅读 · 0 评论 -
BZOJ 3682 Phorni
后缀平衡树考虑如果可以离线,只需构出后缀数组套上线段树。在线的话我们需要一个在线的后缀数组,结合题意中后缀的含义,用后缀平衡树即可。#include<set>#include<cstdio>#include<algorithm>#define N 800005using namespace std;namespace runzhe2000{ typedef double db;原创 2017-04-27 23:34:32 · 535 阅读 · 0 评论 -
51Nod 1600 Simple KMP
SAM+LCT/树剖线段树一个点的深度就是有多少个以这个点结尾的后缀等于前缀。fail树性质不太够,不好下手,直接考虑答案的贡献。对于两个相等的区间[l,r]&[x,y]其中l#include<cstdio>#include<cstring>#include<iostream>#define N 100005#define MOD 1000000007#define A 28#defin原创 2017-04-27 23:31:05 · 564 阅读 · 0 评论 -
SPOJ 1812 LCS2
后缀自动机对于其中一个串建出SAM,把别的串S放在上面跑。对于每一个经过的节点记录串S能贡献给这个节点的max,再对每一个跑过的串在这个节点上取min,最终节点里min贡献的max就是答案。显然一个串能贡献一个节点,就能贡献这个节点的所有祖先,即fail树上到祖先的链都要更新。#include<cstdio>#include<algorithm>#include<cstring>#define原创 2017-04-02 00:27:01 · 311 阅读 · 0 评论 -
BZOJ 3473 字符串
广义后缀树+set子串问题就考虑后缀数据结构。考虑一棵后缀树,一个树上的串合法,当且仅当这个串在至少k个串的后缀树链的并上。那就用SAM做出后缀树,用set维护一个点的链并,即哪些串经过了这个点。然后枚举每一个串跑SAM,对于一个位置i,暴力跳fail直到链并不小于k为止。广义SAM和单串SAM的差别就是刚开始extend的时候要判断是否有一个状态已经包含了当前要增加的状态并且判断这个状态的len和原创 2017-03-29 22:08:17 · 485 阅读 · 0 评论 -
BZOJ 4032 [HEOI2015]最短不公共子串
后缀自动机+序列自动机(1)枚举A的子串,在B的SAM上跑一下看是不是B的子串即可。O(n2)O(n^2)(2)枚举A的子串,在B的序列自动机上跑一下看是不是B的子序列即可。O(n2)O(n^2)(3)对于一个答案序列s[l…r],一定有s[l…r-1]和s[l+1…r]都是B的子串。考虑枚举B的子串并同时在B的SAM上跑,再枚举下一个字母,如果这新串不是B的子串,即B的SAM上无转移,且是A的子序原创 2017-03-28 21:54:26 · 521 阅读 · 0 评论 -
BZOJ 4566 [Haoi2016]找相同字符
后缀数组 或 后缀自动机后缀数组的做法 O(nlogn)O(nlogn) : 串接起来。要求的就是后缀数组中不属于同一串的后缀的LCP。暴力做O(n2) O(n^2) 。发现我们一直都在区间取min,插一个线段树,每次找出最小的然后分两边做即可。(从大到小做,用并查集维护也很好)。这个方法复杂度不是很优秀,SA常数比较大,需要一个SA的优化技巧 if(m >= n) break; 即如果已经排完了就原创 2017-01-29 22:17:08 · 857 阅读 · 0 评论 -
BZOJ 4516 [Sdoi2016]生成魔咒
后缀自动机插入字符更新fail树即可。#include<cstdio>#include<map>#define N 100005#define A 28using namespace std;namespace runzhe2000{ typedef long long ll; int n; ll ans; struct SAM { map原创 2017-01-29 15:16:37 · 355 阅读 · 0 评论 -
CF 235C Cyclical Quest
后缀自动机几天不碰SAM,已经对SAM一无所知了QAQ求x的同构,等价于把x复制一份贴在后面求xx的长度大于len(x)的子串出现次数,注意要判重。一时智障,把当前SAM匹配的节点的len直接当成真实匹配的len了。。。实际上需要记一个curlen表示当前匹配到哪一位才科学。#include<cstdio>#include<cstring>#define N 1000005#define A原创 2017-01-25 11:51:03 · 484 阅读 · 0 评论 -
BZOJ 4556 [Tjoi2016&Heoi2016]字符串
后缀数组+可持久化线段树+二分啊啊啊智商好低,想了好久。一个直观的想法是在s[a…b]中找到和s[c…d]最接近的串,使得height最大。然而一个很烦的事情是s[a…b]存在一个右边界b,意味着我们需要min一个边界值。遇到这种min啊max啊的东西一般考虑强行分类讨论。于是二分一个答案mid,那能贡献mid答案的串开头一定位于s[a…b-mid+1]之中,那边界的条件就没了,这样就可以直接用he原创 2017-02-10 20:34:41 · 590 阅读 · 0 评论 -
BZOJ 3238 [Ahoi2013]差异
后缀自动机+后缀树有一种不难想到的后缀数组的做法,详见黄学长题解然而我做这题的目的主要是熟悉一下后缀自动机和后缀树- -一个有趣的性质:反串的后缀自动机的parent树就是正串的后缀树,其树上的边权长度=parent树上儿子的len-父亲的len构出后缀树之后就是一个小DP啦。#include<cstdio>#include<cstring> #define N 500010#define S原创 2017-01-01 16:50:49 · 365 阅读 · 0 评论 -
BZOJ 2865 字符串识别
后缀自动机+线段树考虑最终包含点i的仅出现一次的子串长什么样。记这个子串是[l,r]。l < i < r : 即i不碰到左右端点,对于这种情况,可以暴力在SAM上找出所有出现一次的串,用线段树更新答案。l = i ≤ r : 设以r为右端点的出现一次的最短的串为[l’,r],显然要有l≤l’。于是依然可以暴力找出所有出现一次的串,用r来更新[1,l-1]的答案。l ≤ i = r : 设以r为右端点原创 2017-01-14 20:33:00 · 495 阅读 · 0 评论 -
BZOJ 3998 [TJOI2015]弦论
后缀自动机弄子串不是SAM最擅长的事情吗。。。注意到SAM上的每一条路径都代表一个子串,所有子串在SAM上都有唯一路径,即它们一一对应。SAM是个DAG,因此本质不同的子串数就是DAG路径条数。T=0就暴力找第k小路径。T=1就求出每个节点的right大小,然后再找第k小。有一些小细节要考虑好,比如走到一个节点i时i->right不应该忽略,即也可以在i结束,然后再考虑i的转移。#include<c原创 2017-01-14 16:40:30 · 329 阅读 · 0 评论 -
SPOJ 1812 LCS2
后缀自动机求多串的最长共子序列。可以用后缀数组+二分来搞。然而会T。后缀自动机可以做到线性时间。对任意一个串建后缀自动机,用别的串来跑。由于串的每一种不同的子串都唯一对应一个节点,因此用别的串跑的时候记录在匹配到这个节点表示的串(或者说是后缀)的最大长度。再维护最大值的最小即可。注意一个节点被更新则它的所有pre也可以被更新同时注意更新pre的时候l可以直接变为p->pre->len,因为p->pr原创 2016-12-30 22:23:00 · 386 阅读 · 0 评论 -
BZOJ 2251 [2010Beijing Wc]外星联络
后缀数组建出后缀数组,按照排名遍历每一个后缀,对于每一个后缀sa[i],从sa[i]+height[i]枚举每一个子串,即可按字典序枚举所有子串(证明见下)。暴力跳height即可出答案。可以证明每一个子串至多被用上一次,因此时间复杂度O(n^2)。闲着无聊,证明一下为什么这样能够按字典序遍历所有本质不同子串。证明这样能够遍历所有子串。首先,每一个子串一定是一个后缀的前缀,所以一定会被遍历到。其次,原创 2017-01-07 22:42:11 · 328 阅读 · 0 评论 -
BZOJ 4698 Sdoi2008 Sandy的卡片
二分+后缀数组先差分,然后找n个串的最长公共子串。 听说直接KMP O(n2m)O(n^2m) 可过,然而用后缀数组可以优化到 O(nmlogn)O(nmlogn) 做法是把所有串接起来,相邻两串之间用不同大数隔开,做SA。显然如果长度k能有公共子串,那么≤k肯定也可以。于是二分k,把所有连续的heigh值≥k的一段拎出来,看这一段是否包含了1~n的一些子串。有的话意味着存在这样的n个子串,否则不原创 2016-12-24 19:35:52 · 708 阅读 · 1 评论 -
BZOJ 1031 [JSOI2007]字符加密Cipher
把字符串复制一份,接在原串后面,做一遍后缀数组。后缀数组的排名就是原串的排名,就可以直接用啦。#include<cstdio>#include<cstring>#define MAX 200010using namespace std;char s[MAX];int sa[MAX*2], tsa[MAX*2], rank[MAX*2], trank[MAX*2], sum[MAX*2],原创 2016-08-01 22:02:05 · 387 阅读 · 0 评论 -
LOJ 6041 「雅礼集训 2017 Day7」事情的相似度
LCT+SAM+线段树问一个区间里的前缀之间的最长公共后缀,考虑SAM一发,建出反串后缀树,然后求最长公共后缀就变成求最深的LCA。直接维护区间的答案不好做,因此考虑一些离线的算法。莫队不知道能不能做,这里考虑把询问按照右端点排序,然后从左到右扫一遍。扫到i,则维护所有左端点在1~i-1,右端点在i的区间的答案。i新贡献的答案就是i和1~i-1的最公共后缀,也就是后缀树上一个点和其它一些点的最深LC原创 2017-06-24 17:34:53 · 1584 阅读 · 0 评论