KMP算法基础

KMP算法基础


AcWing 831. KMP字符串

原题链接

给定一个模式串 S S S,以及一个模板串 P P P,所有字符串中只包含大小写英文字母以及阿拉伯数字。

模板串 P P P 在模式串 S S S 中多次作为子串出现。

求出模板串 P P P 在模式串 S S S 中所有出现的位置的起始下标。

输入格式

第一行输入整数 N N N,表示字符串 P P P 的长度。

第二行输入字符串 P P P

第三行输入整数 M M M,表示字符串 S S S 的长度。

第四行输入字符串 S S S

输出格式

共一行,输出所有出现位置的起始下标(下标从 0 0 0 开始计数),整数之间用空格隔开。

数据范围

1 ≤ N ≤ 1 0 5 1≤N≤10^5 1N105

1 ≤ M ≤ 1 0 6 1≤M≤10^6 1M106

输入样例:

3
aba
5
ababa

输出样例:

0 2

时/空限制: 1s / 256MB
来源: 模板题
算法标签: KMP

yxc’s Solution

KMP的思考方式和一般的单调队列与双指针算法是类似的,或者说和一般的做题思路是类似的.

  1. 暴力算法怎么做;
  2. 如何去优化.
  • 暴力枚举:
s[N] // 要进行比较的字符串
p[M] // 模板串
for (int i = 1; i <= n; i ++ ) {
    
   bool flag = true; // 表示匹配是否成功
   for (int j = 1; j <= m; j ++ )
       	if (s[i + j - 1] != p[j]) {
    
           	flag = false;
           	break;
       	}
}
  • KMP习惯字符串下标从 1 1 1 开始(当然,从 0 0 0 开始也有对应的写法).
  • 考虑优化:

    • 假设字符串 s s s i i i 这个位置开始匹配,匹配到 i + k i+k i+k 这个位置之前都有 s i ’ = p j ’ ,    i ′ ∈ [ i , i + k ) ,    j ′ ∈ [ 1 , 1 + k ) s_{i’}=p_{j’},\;i'\in[i,i+k),\;j'\in[1,1+k) si=pj,i[i,i+k),j[1,1+k)
    • s i + k ≠ p 1 + k s_{i+k} \not= p_{1+k} si+k=p1+k 时,如果是暴力做法,则会让 i i i 往后移动一次并重新匹配;
    • 由于已经匹配了这么多了,所以是有一些额外信息在里面,如果可以利用这些额外信息,就可以帮助我们少枚举一些东西;
  • 考虑 模式串 P P P 最少往后移动多少,可以继续从 i + k i+k i+k 这个位置匹配


    图 1
    • 如果模式串 P P P 能够往后移动 x x x 次,说明 s i ’ = p j ’ ,    i ′ ∈ [ i + x , i + k ) ,    j ′ ∈ [ 1 , 1 + k − x ) s_{i’}=p_{j’},\;i'\in[i+x,i+k),\;j'\in[1,1+k-x) si=
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值