【GDOI2014】beyond
Description
有两个长度为n的字符串s,st,找出两个串前i个可以循环同构的最大长度。
Solution
很容易想到在s中枚举一个分界点i左边的字符
然后,很容易想到求得一个exa[i]为st的s从i开始的字符串最长公共前缀的长度。求得一个exb[i]为s的st从i开始的字符串最长公共前缀的长度。
那么当枚举到分界点为i时,设exa[i+1]为l,那么st[1..l]与s[i+1..i+l]相等。
那么再在st中从1..l+1枚举一个j使得exb[j]+1>=i,那么就是已经循环同构了,那答案就是i+j-1。因为s[i+1..i+exa[i+1]]与st[1..exa[i+1]]相等,1<=j<=i+1,st[j+1..j+exb[j+1]]与s[1..exb[j+1]]相等,至少有s[1..i]=st[j..i+j-1],因为s[i+1..i+exa[i+1]]=st[1..j],exa[i+1]>j,所以至少有i+j-1
得到exa,exb自然用的是exkmp——>扩展kmp
O(n^2)
自然时间会超。
Optimization
使用并查集。
用f[i]存储一个exb[i+1]>=i节点,因为每次更新的是前缀的长度,当前前缀包含前面的前缀,所以可以向前递进,跟kmp的思想差不多。初始值自然是f[i]=i-1。
每次查询时,一直向上递进到一个exb[i+1]>=i的节点即可。
O(n);
Code