P4094 [HEOI2016/TJOI2016]字符串
传送门
题目描述
佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了一个长为$n$的字符串s,和$m$个问题。佳媛姐姐必须正确回答这$m$个问题,才能打开箱子拿到礼物,升职加薪,出任CEO,嫁给高富帅,走上人生巅峰。每个问题均有$a,b,c,d$四个参数,问你子串$s[a..b]$的所有子串和$s[c..d]$的最长公共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?
输入输出格式
输入格式:
输入的第一行有两个正整数$n,m$,分别表示字符串的长度和询问的个数。接下来一行是一个长为$n$的字符串。接下来$m$行,每行有$4$个数$a,b,c,d$,表示询问$s[a..b]$的所有子串和$s[c..d]$的最长公共前缀的最大值。
输出格式:
对于每一次询问,输出答案。
输入输出样例
输入样例#1:
5 5
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4
输出样例#1:
1
1
2
2
2
说明
对于$10\%$的数据,$1 \le n,m \le 300$
对于$40\%$的数据,$1 \le n,m \le 3000$,字符串中仅有$a$,$b$
对于$100\%$的数据,$1 \le n,m \le 10^5$,字符串中仅有小写英文字母,$a \le b,c \le d,1 \le a,b,c,d \le n$
分析
我们首先可以看出本题答案是有单调性的。
因为如果一个串可以,那么它的前缀也一定可以,即如果一个答案满足题意,那么所有小于它的答案也都满足题意。
既然有单调性,那么我们可以二分。
我们二分$s[c…d]$的前缀长度为$len$。
那么显然如果满足题意,那么$s[c…c+len-1]$一定是$s[a…b]$的子串。
现在问题就转化成了给你一个串,判断它是不是另一个字符串的子串。
似乎很多人都是用$SA$做的,可是本蒟蒻不会$SA$…
所以我们想想$SAM$的做法。
其实很好想如果它是子串,那么它一定在另一个串的$Endpos$中。
我们就只需要判断是不是这个串的$Endpos$中有$a+len-1…b$中任何一个数出现。
这个显然权值线段树可以搞定。
那么我们怎么求$Endpos$集合?
线段树合并就行了。
还有一个小细节就是,不是直接在子串在$SAM$上的节点的线段树里找,而是一直往上跳祖先,直到这个节点的$len_i$是满足$len_i \ge len$的最小值。因为长度越小$Endpos$的元素越多,找到的概率就越大(说人话就是不会漏解)。
另外,我不知道用$SAM$为什么一定要把串翻过来,不翻也照样做啊?
吐槽:Owen_codeisking题解中的$SAM$解法阵亡了,弄得我对拍的时候一直以为我打错了,浪费了好多时间。
hack数据:
4 1
mktk
3 4 1 4
正确输出:
1
参考资料
mrclr的 [HEOI2016/TJOI2016]字符串
Owen_codeisking的 [HEOI2016/TJOI2016]字符串(后缀数组+二分+主席树/后缀自动机+倍增+线段树合并)
代码
1 |
|