给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。 本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下: 数据0:小规模字符串,测试基本正确性; 数据1:随机数据,String 长度为 10 5 ,Pattern 长度为 10; 数据2:随机数据,String 长度为 10 5 ,Pattern 长度为 10 2 ; 数据3:随机数据,String 长度为 10 5 ,Pattern 长度为 10 3 ; 数据4:随机数据,String 长度为 10 5 ,Pattern 长度为 10 4 ; 数据5:String 长度为 10 6 ,Pattern 长度为 10 5 ;测试尾字符不匹配的情形; 数据6:String 长度为 10 6 ,Pattern 长度为 10 5 ;测试首字符不匹配的情形。
时间: 2023-11-28 20:47:41 浏览: 191
字符串匹配
好的,这道题目可以用多种算法来解决,包括暴力匹配、KMP算法、Boyer-Moore算法等。我们可以先讲一下暴力匹配算法的思路和实现,再介绍其他算法。
暴力匹配算法的思路很简单,就是从字符串 String 的第一个字符开始,逐个和 Pattern 进行比较,如果匹配成功就继续比较下一个字符,否则就从下一个字符重新开始匹配。具体实现代码如下:
```python
def find_substring(string, pattern):
n = len(string)
m = len(pattern)
for i in range(n - m + 1):
j = 0
while j < m and string[i+j] == pattern[j]:
j += 1
if j == m:
return string[i:]
return "Not Found"
```
这里用了两个指针 i 和 j,分别指向 String 和 Pattern 的当前比较位置。时间复杂度为 O(nm),其中 n 和 m 分别为 String 和 Pattern 的长度。
接下来我们介绍 KMP 算法,它可以在 O(n+m) 的时间复杂度内解决这个问题。KMP 算法的核心思想是利用已经匹配成功的信息,尽量减少不必要的比较次数。具体实现代码如下:
```python
def kmp_next(pattern):
n = len(pattern)
next = [0] * n
i, j = 1, 0
while i < n:
if pattern[i] == pattern[j]:
j += 1
next[i] = j
i += 1
elif j > 0:
j = next[j-1]
else:
next[i] = 0
i += 1
return next
def find_substring(string, pattern):
n = len(string)
m = len(pattern)
next = kmp_next(pattern)
i, j = 0, 0
while i < n and j < m:
if string[i] == pattern[j]:
i += 1
j += 1
elif j > 0:
j = next[j-1]
else:
i += 1
if j == m:
return string[i-m:]
else:
return "Not Found"
```
KMP 算法中的 kmp_next 函数用来计算 Pattern 的前缀和后缀相同的最长子串长度,将其保存在 next 数组中。find_substring 函数中,i 和 j 分别指向 String 和 Pattern 的当前比较位置,next 数组用来跳过已经匹配成功的字符。时间复杂度为 O(n+m)。
最后我们介绍 Boyer-Moore 算法,它可以在最坏情况下 O(nm) 的时间复杂度内解决这个问题,但在实际应用中效果很好。Boyer-Moore 算法的核心思想是从字符串末尾开始匹配,尽量跳过不必要的比较,同时利用启发式规则来快速确定跳过的长度。具体实现代码如下:
```python
def boyer_moore(string, pattern):
n = len(string)
m = len(pattern)
if m == 0:
return 0
last = {}
for i in range(m-1, -1, -1):
if pattern[i] not in last:
last[pattern[i]] = i
i = m - 1
j = m - 1
while i < n:
if string[i] == pattern[j]:
if j == 0:
return string[i:]
else:
i -= 1
j -= 1
else:
if string[i] not in last:
i = i + m
else:
k = last[string[i]]
i = i + m - min(j, k+1)
j = m - 1
return "Not Found"
```
Boyer-Moore 算法中的 last 字典用来保存 Pattern 中每个字符最后出现的位置,i 和 j 分别指向 String 和 Pattern 的当前比较位置,根据启发式规则来跳过不必要的比较。时间复杂度最坏为 O(nm),但在实际应用中通常都能达到线性的时间复杂度。
以上就是三种不同的匹配算法,可以根据不同的数据情况选择合适的算法来进行实现。
阅读全文