数据结构(一)字符串匹配

概述

这篇文章主要是总结一下字符串匹配问题中最常用的算法。
我们的问题是这样的:

有一个 t 字符串,可能是 'hello world',有一个 p 字符串,可能是 'lo',现在希望能通过程序找出 t 字符串中是否包含 p 字符串,如果包含,则返回第一个匹配上的子串的位置。

1. 朴素算法

朴素算法的思想很简单,其实就是我们日常生活中使用人脑求解的思路,先拿 t 串的 第一个位置开始,与 p 串从头开始进行比较,直到某个字符匹配不上,则再从 t 串的第二个位置开始,与 p 串从头开始比较……以此类推,直到某一次与 p 串完全匹配,则返回对应位置。

# -*- coding: UTF-8 -*-

def indexOf(t, p):
    i = 0
    j = 0
    while i < len(t) and j < len(p):
        # 每次从子串的头开始匹配,一个一个字符向后
        if(t[i] == p[j]):
            i = i + 1
            j = j + 1
        # 匹配失败,则需要回溯 i 值
        else:
            i = i - j + 1
            j = 0

    if j == len(p):
        return i - j
    else:
        return -1


t = 'hello world'
p = 'or'

print(indexOf(t, p))

2. KMP 算法

相比起朴素算法,KMP 算法的思路没有那么直观,找了很多资料才最终看明白。KMP 算法的关键是不对 t 串比较的字符位置进行回溯,回溯操作只针对 p 串,而回溯操作是根据提前计算好的 next 数组,其中保存了回溯的位置。

https://www.zhihu.com/question/21923021/answer/281346746

# -*- coding: UTF-8 -*-

def indexOf(t, p):
    if p == None or p == '':
        return -1
    
    next = getNext(p)
    i = 0
    j = 0
    while i < len(t) and j < len(p):
        if j == -1 or t[i] == p[j]:
            i += 1
            j += 1
        else:
            j = next[j]
            
    if j == len(p):
        return i - len(p)
    else:
        return -1


def getNext(p):
    if p == None or p == '':
        return None

    if len(p) == 1:
        return [-1]
        
    i = 0
    j = 1
    pos = 2
    next = [0] * len(p)
    next[0] = -1
    while i < len(p) and j < len(p):
        next[j] = i
        if p[i] == p[j]:
            i += 1
            j += 1
        else:
            i = 0
            j += 1
    return next       
            


t = 'habababzabababa'
p = 'abababzabababa'

print(indexOf(t, p))

你可能感兴趣的:(数据结构(一)字符串匹配)