HDU4622 Reincarnation【SAM】】的更多相关文章

HDU4622 Reincarnation 给出一个串,每次询问其一个子串有多少不同的子串 按每个后缀建立\(SAM\)不断往后加字符,然后记录答案,查询的时候直接用即可 //#pragma GCC optimize("O3") //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace std; function<…
[题目大意] 求两个字符串的最长公共子串. [思路] 对第一个字符串建立后缀自动机,第二个字符串去匹配.cnt记录当前最长公共子串的长度,而ret记录答案. p代表位置指针,初始在rt位置. 对于第二个字符串的某一位s[i],如果当前有s[i]孩子,则cnt+1,继续往后移动:否则沿着pre指针返回.如果pre指针返回到0,则将p回到rt,cnt清空为0;否则如果中间有点拥有s[i]孩子,cnt=step[]+1. 为什么cnt=step[]+1?不要忘了后缀自动机的本质是维护后缀,沿着pre指…
[题目大意] 求一个循环数列的最小表示法. [思路] 最小表示法的正解:★ SAM乱搞,和前面的POJ那道一样.然而MLE了,当作学习一下map的用法^ ^ map的使用方法(来源:☆) 一.map的说明    1   头文件   #include   <map>     2   定义   map<string,   int>   my_Map;   或者是typedef     map<string,   int>   MY_MAP;   MY_MAP   my_Ma…
[题目大意] 给出一个字符串,求第k大的子串.(输入1表示子串可重复,0表示不可重复) [思路] 显然,k大子串是后缀自动机的经典题型,可以利用后缀自动机的性质来解决.对于字符串 [前铺1]"abcbc",我们可以画出它的后缀自动机,如下图: Pre树类似于AC自动机中的fail树,即将pre方向形成一棵树.对于上图,它的pre树如下: [前铺2]考虑字符串s的任意非空子串t.我们称终点集合right(t)为:s中所有是t出现位置终点的集合.例如:对于字符串ATCGTCGT来说,所有的…
[题目大意] 求一个循环数列的最小表示法. [思路] 把原创复制一遍放在后面,建立SAM,从s按字典序开始跑长度L即可. 板子来源(作者见连接内):…
原文链接https://www.cnblogs.com/zhouzhendong/p/HDU4622.html 题目传送门 - HDU4622 题意 多组数据. 对于每一组数据,给定一个字符串 s ,以及 m 次询问,每次询问 s 的一个子串的不同子串个数. $|s|\leq 2000,m\leq 10000$ 题解 直接 SAM 预处理一下每一个区间的答案就可以了. 代码 #include <bits/stdc++.h> using namespace std; typedef long l…
题意 求出多个串的最长公共子串. 分析 刚学SAM想做这个题的话最好先去做一下那道codevs3160.求两个串的LCS应该怎么求?把一个串s1建自动机,然后跑另一个串s2,然后找出s2每个前缀的最长公共后缀.那么多个的时候,我们也用这种类似的方法,但是我们求最长公共后缀的时候要求第一个串的.我们把其中一个串建SAM,然后把其他的串都在上面跑,维护两个值,Max[u]和Min[u].自动机中每个状态u的Right存的是结尾集合.那么对于一个字符串,我们可以求出他和自动机中每个状态的最长公共后缀.…
做得心 力 憔 悴 Description 你有一个字符串S,一开始为空串,要求支持两种操作 在S后面加入字母C 删除S最后一个字母 问每次操作后S有多少个两两不同的连续子串 Input 一行一个字符串Q,表示对S的操作 如果第i个字母是小写字母c,表示第一种加字母c的操作 如果为-表示删除操作,保证所有删除操作前S都非空 |Q|<=10^5 Output 输出|Q|行,第i行表示i个操作之后S内有多少个不同子串 题目分析 陈老师神题x2,暂时只会做法一. 做法一:暴力回退 还是自己菜啊……这么…
网上有篇题解写的是线段树合并维护求值? 题目描述 有一个只包含小写字母,长度为 $n$ 的字符串 $S$ .有一些字母是好的,剩下的是坏的. 定义一个子串 $S_{l\ldots r}$是好的,当且仅当这个子串包含不超过 $k$ 个坏的字母. 求有多少个不同的满足以下要求的字符串 $T$ : $T$ 作为 $S$ 的子串出现过. 存在一个 $T$ 出现的位置 $[l,r]$ ,满足 $S_{l\ldots r}$​ 是好的. 输入格式 第一行有一个字符串 $S$ . 第二行有一个字符串 $B$…
对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会被更新,需要最后按拓扑序向上更新一边 其实二分+hash就行 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=10005; int n,m,ch[N…