「CTS2019 | CTSC2019」重复(Kmp)
「CTS2019 | CTSC2019」重复(Kmp)
Part1
首先我们考虑对于一个已经确定的$t$串,如何检查是否合法
对于$s$串建立$\text{kmp}$($\text{kmp}$自动机当然可以),
如果当前$\text{kmp}$指针$j$在$\text{fail}$树上的祖先所对应的所有下一个位置$s[ancestor+1]$中,存在一个字符,$t$中当前位置的字符$t[i]<s[ancestor+1]$
那么就是存在一个”有意义的串”,并且这个串和s串第一个不同的位置就是$ancestor+1$
所以可以预处理一个$fail$树上祖先最大的$s[ancestor+1],Max[state]$
1 | rep(i,1,n) Max[i-1]=s[i]; |
配合dfs枚举,可以拿到pts10
Part2
设状态转移为$Trans[state][c]$
把kmp状态压进dp状态里
如果把问题直接放到无穷意义下来看
那么跑够长度之后,后面的任意加入$m$次字符都会构成一个循环
枚举循环开始状态为$st$,$\text{dp}$走了$m$步回到$st$的方案数
如果计算合法方案数,那么还要多一维,所以直接计算不合法方案,也就是
$Trans[state][Max[state]..25]$这一段转移是不会出现合法情况的
最后减一下
复杂度$O(m\cdot n^2)$
1 | namespace pt2{ |
Part3
观察上面一档情况,合法的转移$Trans[state][Max[state]..25]$
如果枚举下一个字符$c>Max[state]$,那么在$s$串中就找不到任何匹配了,下一个状态就是$0$
否则,下一个状态就是$Trans[state][c]$
也就是说,每个点出发其实只有两种情况,一种是一定会经过$0$的
所以对于这个环是否经过$0$进行讨论
如果不经过$0$,那么考虑直接从$st$出发走$m$步非0转移即可
经过$0$的,预处理一个从$0$出发,走了$i$步第一次回到$0$的方案数
$[st\rightarrow 0,0\rightarrow 0,0\rightarrow 0…,0\rightarrow st]$
长成这个样子的转移
枚举第一个$st\rightarrow 0$的时间,后面可以预处理出来
复杂度$O(n\cdot m)$
1 |
|