利用 nxt 数组使字符串匹配降到 \(O(n)\)。
next
i从2开始,j从0开始
i和j+1匹配不上,j跳nxt
匹配就j++
nxt[i] = j
1 | for (int i = 2, j = 0; i <= blen; ++i) { |
匹配
i从a的1-len,j从0开始
a[i]
和b[j+1]
匹配不上就j跳nxt
否则j++
j到blen则匹配完一次,跳nxt
1 | for (int i = 1, j = 0; i <= alen; ++i) { |
以上为远古文章。
扩展 kmp
给出长为 \(n\) 的字符串 \(s\)。
\(\mathcal O(n)\) 处理 \(z\) 函数:\(z_i=|\operatorname{LCP}(s,s[i:])|\)。
记录 \(r\) 最大的一对 \(l,r\) 满足 \(r=l+z_l-1\)。
设从前到后处理到 \(i\),当 \(i\le r\) 时,初始化 \(z_i=\min\{z_{i-l+1},-i+1\}\),否则为 \(0\)。
然后暴力匹配 \(s[i+z_i]\) 和 \(z[z_i+1]\)。
每个字符最多被暴力匹配 \(1\) 次,复杂度 \(\mathcal O(n)\)。
1 | z[1] = n; |