题目

思路来源
小羊肖恩
题解
羊神这个做法tql,当时只是机械地写,过了之后再想想,才觉得确实是nb
先扩展kmp(Z函数)预处理出来数组,记z[i]为i往后可以和前缀匹配的最大长度
对于每个询问(p,cnt),先离线归位到每个p所在的vector内,
然后扫描线,每个i有一个[i,i+z[i]-1]的区间,在这个区间内以j结尾时,和前缀的lcp固定为[i,j]
对于每个i,先特判只出现一次的情况
对于大于一次的情况,先二分当前最大的可行长度x,
这个需要预处理mn[i][j]表示前i个字符出现j次时的结尾处的最小下标,没有的话就是n+1
对于位置p,出现次数cnt,二分找到满足mn[x][cnt]<=p的最大x,
长度x的前缀出现了cnt次,那么短于长度x的前缀一定出现了cnt次,
然后[i,i+z[i]-1]的扫描线保证了以p结尾的一定是一个当前合法的A串,
这就保证了A在开头和结尾均出现,且总的出现次数不少于cnt次了
一开始暴力双指针预处理mn超时了,后来改成在set上二分就ac了
因为长的串对应的位置一定包含短串,所以可以按zi从大到小释放位置,放进set,在set里二分
代码
#include<bits/stdc++.h&


最低0.47元/天 解锁文章
530

被折叠的 条评论
为什么被折叠?



