KMP

想了解更多请查看:https://blog.csdn.net/qq_55364042/article/details/130098343?spm=1001.2014.3001.5501

KMP的设计之初是为了实现在一个大字符串A中找出一个某个小字符串a

例(1):在'deabcfgabcabcd' 中找出‘abcabc’

如果纯暴力的话 时间复杂度为O(n^2)

下标跳转数组

现在让我们假设有一种数组(arr),他的每一位下标代表了截止到当前为止’前后缀相同的‘‘最长的’长度,例(2):abcabc 的arr为【0,0,0,0,1,2,3】,注意我们的下标从1开始数

               例(3):aaaa的arr为【0,0,1,2,3】

如果说我们的a有这样一个数组,那么就会很方便

思维

设:i为A的下标指针,j为a的下标指针,j最少会比i小1且从外加的一个空字符开始

当A【i】==a【j】:  i+=1  ,j+=1

当A【i】!=a【j】 :i=i  ,   j=arr跳转至第一个等于A【i】的位置,证明如下

首先A是比a长的,所以在A中找a的时候,A中要有一个开头下标 设为q

设A【q~(i-1)】等于a【0~j】,那么A【q~(i-1)】.前缀/后缀  == a【0~j】.前缀/后缀

又 前后缀是相等的,所以A【q~(i-1)】.后缀  == a【0~j】.前缀

所以j可以通过arr跳转至a的前缀结尾下标

那么当我们在A中找a的时候,每次匹配失败时,a的j就不是暴力的每次跳到开头 而是跳到前缀结尾处,那么就节省了大量的时间,可以说是O(n)的

代码实现

A=' '+input()#大串
a=' '+input()#小串
arr=[0 for i in range(len(a))]#下标跳转数组
j=0
for i in range(2,len(a)):#跑出下标跳转数组
    while j and a[j+1]!=a[i]:#跳转至可匹配的前缀结尾处
        j=arr[j]

    if a[j+1]==a[i]:
        j+=1
    arr[i]=j

def Find(A,a,arr):
    j=0
    for i in range(1,len(A)):
        while j and a[j+1]!=A[i]:
            j=arr[j]
        if a[j+1]==A[i]:
            j+=1
            if j==len(a)-1:
                return True
    return False

if len(A)<len(a):
    print('输入有误')
elif Find(A,a,arr):
    print('A中有a')
else:
    print('A中无a')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自 在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值