2022沈阳D题题解
2022沈阳D题题解
这题在VP的时候成功把我卡死了,原因是我一直没有想到用KMP去大力匹配,导致我的算法复杂度一直是O(n^2logn),然后就很典的T了。
VP完了之后想各种优化卡过去,但是都失败了,跑校园跑的时候突然想到怎么解了。
现在我是这样看待这个问题的,这个问题应该是可以被拆分成两个部分:
1.从字符串a中找到一个连续子串,在一侧补上之后可以满足题目要求的条件
2.在找到这个连续子串以后,在字符串b里面匹配,找有多少个字符串匹配。
第一步可以通过观察规律得到,这里可以举一个例子:abcd...abcd
观察这个字符串,我们发现从a到a之间显然是有一个,从b到a,从b到b之间显然各有一个,那么以此类推,我们发现我们要做的,其实就是枚举前缀的最后一个字母,然后在右侧找这个字母,并且dp得到这个字母的最大前缀长度(与前面枚举的下标前缀要匹配)。
那么显然,可以通过if(s[i-1]==s[j-1]) lst[j]=lst[j-1]+1;来实现这个DP,值得注意的是,为了保证前后的前缀是一致的,与当前的枚举的字母不匹配的下标的lst都需要清零。
第二步相对来说可能会更简单。
我是这样构思的,把字符串a,枚举每一个下标为开端,最后一个下标为尾,这样拆分出n条链。
然后考虑把字符串b和这n条链进行匹配,第一步中得到的有效字符串在这一步中需要提前加在链的节点上,然后创建next数组的时候考虑路径压缩把父亲节点的值都求和在当前节点。
然后就是大力匹配求和,对每个字符串都做一遍就行了。
没有具体实现,因为上面的思路是我口嗨的,懒得写。