Processing math: 100%

CF1063F String Journey DP、SAM、线段树

传送门


为了方便把串反过来,条件变为titi+1的真子串,答案显然不变。

一件重要的事情是必定存在一种最优解,字符串序列{t}满足|ti|=i

考虑DP:设fi表示字符串序列{t}的最后一个串的结尾位置为i时,|t|的最大值。不难发现如果fi=x,那么一定存在最后一个串结尾位置为i、长度在[1,x]内的字符串序列。

因为有fifi1+1(因为对于一个能够满足序列长度为fi、最后一个串结尾为i的字符串序列t,把第一个字符串删掉,然后把其他的串的最后一个字符删掉,就可以得到序列长度为fi1、最后一个串结尾为i1的一个合法的字符串序列),所以可以从大到小枚举fi的合法取值,这里的总check次数是O(n)的。

那么问题变成如何check。考虑我们实际上只需要满足s1,ifi中是否存在一个sifi+1,i的子串满足该串的结尾的f值大于等于fi1。注意到可能满足条件的只有两个子串(sifi+1,i1sifi+2,i),所以我们只需要知道这些点所有ifi的endpos中的f值的最大值。注意到ifi是单调不降的,所以我们可以使用一个指针维护当前询问的前缀,在线段树上做单点修改、子树查询最大值即可。

代码

posted @   cjoier_Itst  阅读(273)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示