匹配统计

这个是对\(f[i]\)数组的扩展,\(f[i]\)求的是\(A\)的后缀与\(B\)的前缀匹配的最大长度,而这道题目是求\(A\)的前缀与\(B\)的前缀匹配的最大长度

注意不能简单地将\(A\)翻转然后跑KMP,因为\(A\)翻转了匹配的方向不会翻转。比如说\(ABC\)\(AB\)匹配长度为\(2\),反转后为\(CBA\),(用KMP求出的)匹配长度显然为\(0\),但我们想要的还是\(2\)

这道题目有hash+二分的做法,比较好想,下面介绍KMP的做法

我们先考虑一个暴力的做法,我们把\(B\)挨个挨个从\(A\)的某个位置开始进行匹配,看最多能匹配多少个,设为\(x\),然后把\(cnt[x]++\),最后查询的时候直接输出\(cnt[x]\)即可;但是为了利用KMP,我们不这么做暴力,而是对每次的\(x\),将\(cnt[1],cnt[2],...,cnt[x]\)都加一。统计答案\(x\)时,考虑\(cnt[x]\),显然此时\(cnt[x]\)多加了,多余的部分是因为匹配长度恰好\(x+1,x+2,x+3...\)的时候让\(cnt[x]\)增加了,于是我们减掉这些增加的量就是答案,此时利用后缀和思想即可

那我们怎么用KMP呢?我们考虑利用\(f[i]\)这个数组

接下来就看看这篇题解

这篇题解怎么保证不重不漏呢?考虑我们上面的暴力算法,在暴力的过程中,我们给每一个匹配长度分类,如下

假设某一次\(A\)\(B\)如上,橙色方块是能匹配的最大长度,假设是4

那我们朴素的加\(cnt\)数组的话,就要给\(cnt[1-4]\)都加\(1\),我们如果以每一个长度的末尾为标准,将每一个长度放到这个标准以内,比如

我们将\(B[1-1]\)分配给\(A[i]\)这个位置,\(B[1-2]\)分配给\(A[i+1]\)这个位置,\(B[1-3]\)分配给\(A[i+2]\)这个位置

那么在暴力的过程后\(A[i]\)就有对应的分配了,然后在题解中,我们对\(A[i]\)做那个循环加法,就相当于给\(A[i]\)分配的每一个长度的\(cnt\)做加法,此时就可以知道是不重不漏的

posted @ 2024-01-17 20:15  最爱丁珰  阅读(2)  评论(0编辑  收藏  举报