📅  最后修改于: 2023-12-03 14:55:50.229000             🧑  作者: Mango
当需要在一个字符串中查找特定的子串时,就需要进行字符串模式匹配。在计算机科学中,一般有两类字符串模式匹配算法,一种是基于暴力匹配的朴素算法,另一种是基于自动机的KMP算法。
朴素算法是一种简单粗暴的字符串匹配算法,基于字符串中每一个字符与子串首字符的比较,在发现第一个匹配字符后进行接下来字符的匹配。如果发现不匹配字符,则回到原字符串的下一个位置继续匹配。如果字符串后面部分无法匹配,则将子串向后移一位并从头重新开始。
朴素算法的时间复杂度为O(nm),其中n为主串长度,m为子串长度,当子串和主串完全不符合时,需要比较n-m+1次。
def naive_search(pattern, text):
matches = []
n, m = len(text), len(pattern)
for i in range(n - m + 1):
j = 0
while j < m and text[i+j] == pattern[j]:
j += 1
if j == m:
matches.append(i)
return matches
KMP算法是一种更快的字符串匹配算法,基于预处理模式串中的信息,尽可能避免在主串中回溯匹配字符。在KMP算法中,主要是利用匹配失败时的信息,即在匹配失败后不回到主串起始位置,而是从模式串中重新寻找匹配位置。
KMP算法的时间复杂度为O(n+m),其中n为主串长度,m为子串长度,最坏情况下需要比较2n次。
def kmp_table(pattern):
n = len(pattern)
prefix = [-1] * n
j = -1
for i in range(1, n):
while j >= 0 and pattern[j+1] != pattern[i]:
j = prefix[j]
if pattern[j+1] == pattern[i]:
j += 1
prefix[i] = j
return prefix
def kmp_search(pattern, text):
matches = []
n, m = len(text), len(pattern)
prefix = kmp_table(pattern)
j = -1
for i in range(n):
while j >= 0 and pattern[j+1] != text[i]:
j = prefix[j]
if pattern[j+1] == text[i]:
j += 1
if j == m - 1:
matches.append(i - m + 1)
j = prefix[j]
return matches
朴素算法虽然简单易懂,但是在长字符串和长模式串的匹配中会非常低效,因此通常使用KMP算法来进行字符串匹配。KMP算法的主要思想在于通过预处理模式串,尽可能利用已经匹配的信息,减少回溯的次数。