"如何实现字符串的匹配"(python)

题目描述:给定主字符S与模式字符串P,判断P是否是S的子串,如果是,那么找出P在S中第一次出现的下标。

分析与解答:对于字符串的匹配,最直接的方法就是逐个比较字符串中的字符,这种方法比较容易实现,但是效率也比较低下。对于这种字符串匹配的问题,除了最常见的直接比较法外,经典的KMP算法也是不二选择,它能够显著的提高运行效率。

方法一:直接计算法

def match(s, p):
    # 检查参数的合理性
    if s == None or p == None:
        print("参数不合理")
        return -1
    slen = len(s)
    plen = len(p)

    # p肯定不是S的子串
    if slen < plen:
        return -1
    i = 0
    j = 0
    while i < slen and j < plen:
        if list(s)[i] == list(p)[j]:
            # 如果相同,那么继续比较后面的字符
            i += 1
            j += 1
        else:
            # 后退回去重新比较
            i = i - j + 1
            j = 0

            if i > slen - plen:
                return -1
    # 匹配成功
    if j >= plen:
        return i - plen
    return -1

if __name__ == "__main__":
    s = "xyzabcd"
    p = "abc"
    print(match(s, p))

方法二:KMP算法

def getNext(p, nexts):
    i = 0
    j = -1
    nexts[0] = -1
    while i < len(p):
        if j == -1 or list(p)[i] == list(p)[j]:
            i += 1
            j += 1
            nexts[i] = j
        else:
            j = nexts[j]

def match(s, p, nexts):
    # 检查参数的合理性,s的长度一定不会小于p的长度
    if s == None or p == None:
        print("参数不合理")
        return -1
    slen = len(s)
    plen = len(p)

    # p肯定不是s的子串
    if slen < plen:
        return -1
    i = 0
    j = 0
    while i < slen and j < plen:
        print("i="+str(i)+","+"j="+str(j))
        if j == -1 or list(s)[i] == list(p)[j]:
            # 如果相同,那么继续比较后面的字符
            i += 1
            j += 1
        else:
            # 主串i不需要回溯,从next数组中找出比较的模式串的位置j
            j = nexts[j]
    # 匹配成功
    if j >= plen:
        return i-plen
    return -1

if __name__ == "__main__":
    s = "abababaabcbcbcb"
    p = "abaabc"
    lens = len(p)
    nexts = [0]*(lens + 1)
    getNext(p, nexts)
    print("next数组为:"+str(nexts[0]))
    i = 1
    while i < lens - 1:
        print(","+str(nexts[i]))
        i += 1
    print('\n')
    print("匹配结果为:"+str(match(s,p,nexts)))

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值