ABC213

AtCoder Beginner Contest 213

E - Stronger Takahashi

题意

给出一个迷宫: .代表可以走的道路,#代表墙,你可以花费一点力气打破任意一个 2×22\times 2 区域中的所有的墙

请问从迷宫的左上角走到右下角,最少要花费多少力气?

思路

这道题相比F题要水多了,但我并没看出来

这题可以相当于建图跑最短路,但由于图上的边权只有0和1,所以只需要用BFS就能完成,这就是01BFS

01BFS通过维护双端队列,使得队头元素是单增的,如果当前使用边权为0的边进行的松弛操作,那么把新的顶点push到队头,否则就是用边权为1的边进行的松弛操作,把新的顶点push到队尾

如此操作,可以保证队列中的元素都是形如00…0011…11…

关于这道题,考虑当前在格点T

.***.
*****
**T**
*****
.***.

那么*都是可以通过花费一次力气到达的格点,而不需要力气到达的格点只有和T相邻的4个格点并且它们是.

则时间复杂度为 O(21NM)O(21NM)

F - Common Prefixes

题意

定义字符串函数 f(S,T)f(S,T) 为字符串 S,TS, T 的最长公共前缀,也就是LCM

给出一个长度为 NN 的字符串 SSSiS_i 表示从 SS 的第 ii 个字符开始的 SS 的后缀
abcdS2=bcd,S3=cdS_2=bcd,S_3=cd

对于每个 k=1,,Nk=1,\ldots,Nf(Sk,S1)+f(Sk,S2)++f(Sk,SN)f(S_k,S_1)+f(S_k,S_2)+\ldots+f(S_k,S_N)

思路

比赛时速度还是太慢了,对SAM还是不够熟练,由于公共前缀不好处理,考虑转为公共后缀,只需要将字符串反转后,倒序输出答案即可

那么 i=1Nf(Sk,Si)\sum_{i=1}^N f(S_k,S_i) 就是求字符串 s1s2sks_1s_2\ldots s_k 的每个后缀在 SS 中的出现次数

这个问题使用后缀树很容易解决,用sz数组代表SAM中每个顶点right集合的大小,mx数组表示该顶点的right集合中的最大长度

先找到 SkS_k 对应的节点 pp,然后暴跳 prtprt 数组,那么以 skmx[p]+1sks_{k-mx[p]+1}\ldots s_kSS 中的出现次数就是 sz[prt[p]]sz[p]sz[prt[p]] - sz[p]

那么顶点 pp 对答案的贡献就是 mx[p](sz[prt[p]]sz[p])mx[p] \cdot (sz[prt[p]]-sz[p]),求和即可

但是如果对每个节点都暴跳 prtprt 数组复杂度是 O(N2)O(N^2) 肯定超时,所以还需要记忆化一下

dp[p]dp[p] 为顶点 prt[p]prt[p] 产生的贡献,不记当前顶点 pp 产生的贡献,是因为当前顶点的贡献会和它的而自己顶点的sz大小有关

时间复杂度为 O(N)O(N)


ABC213
https://wty-yy.github.io/posts/53398/
作者
wty
发布于
2021年8月9日
许可协议