Python 多个字符串的最长公共子串
在本文中,我们将介绍如何使用Python找到多个字符串中的最长公共子串。最长公共子串是指在多个字符串中出现的最长连续的子串。
阅读更多:Python 教程
1. 动态规划法
动态规划是解决最长公共子串问题的一种常见方法。思路是使用一个二维数组来记录字符串中每个位置的公共子串长度。
def longest_common_substring(strs):
if not strs:
return ""
dp = [[0] * (len(strs[0]) + 1) for _ in range(len(strs) + 1)]
max_length = 0
end_index = 0
for i in range(1, len(strs) + 1):
for j in range(1, len(strs[0]) + 1):
if strs[i - 1][j - 1] == strs[i - 1][j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
if dp[i][j] > max_length:
max_length = dp[i][j]
end_index = j
return strs[0][end_index - max_length:end_index]
示例:
strs = ["abcdefg", "defgabc", "abcde"]
result = longest_common_substring(strs)
print(result) # 输出:"abc"
上述代码中,我们首先创建了一个二维数组dp,大小为(len(strs) + 1) * (len(strs[0]) + 1),并初始化为0。然后,我们遍历字符串数组和每个字符串的位置,如果当前位置的字符相等,就更新dp数组,并记录最长公共子串的长度和结束索引。最后,我们根据最长公共子串的长度和结束索引截取出结果。
2. 后缀树法
后缀树是另一种解决最长公共子串问题的方法。后缀树是一种特殊的树状数据结构,用于存储一个字符串的所有后缀。
class Node:
def __init__(self, char):
self.char = char
self.children = {}
def longest_common_substring(strs):
if not strs:
return ""
root = Node("")
for s in strs:
curr_node = root
for c in s:
if c not in curr_node.children:
curr_node.children[c] = Node(c)
curr_node = curr_node.children[c]
result = ""
for key in root.children:
stack = [(root.children[key], "", 0)]
while stack:
curr_node, substring, count = stack.pop()
if len(curr_node.children) == 1:
for child in curr_node.children.values():
substring += child.char
count += 1
stack.append((child, substring, count))
elif len(curr_node.children) > 1:
if count > len(result):
result = substring
substring = ""
count = 0
return result
示例:
strs = ["abcdefg", "defgabc", "abcde"]
result = longest_common_substring(strs)
print(result) # 输出:"abc"
上述代码中,我们首先创建了一个根节点,然后遍历每个字符串,构建后缀树。接着,我们从根节点开始遍历树的每个节点,当某个节点的子节点个数大于1时,说明该路径上的字符是公共子串的一部分。我们将这个公共子串与之前记录的结果比较,更新结果。最后,返回找到的最长公共子串。
3. 哈希表法
哈希表法是另一种解决最长公共子串问题的方法。我们可以使用哈希表来记录每个字符串的所有子串和出现的次数,然后找到出现次数与字符串数量相等的最长子串。
def longest_common_substring(strs):
if not strs:
return ""
substrings = {}
for s in strs:
for i in range(len(s)):
for j in range(i + 1, len(s) + 1):
substring = s[i:j]
if substring in substrings:
substrings[substring] += 1
else:
substrings[substring] = 1
result = ""
for substring, count in substrings.items():
if count == len(strs) and len(substring) > len(result):
result = substring
return result
示例:
strs = ["abcdefg", "defgabc", "abcde"]
result = longest_common_substring(strs)
print(result) # 输出:"abc"
上述代码中,我们首先创建了一个空的哈希表substrings,然后遍历每个字符串的所有子串,将子串作为键,出现次数作为值存入哈希表中。接着,我们遍历哈希表中的每个子串,如果子串的出现次数等于字符串数量,且子串长度大于之前记录的结果,就更新结果。最后,返回找到的最长公共子串。
总结
本文介绍了三种解决多个字符串最长公共子串问题的方法:动态规划法、后缀树法和哈希表法。动态规划法适用于字符串数量不多的情况,时间复杂度为O(N^2 × M),其中N是字符串数量,M是字符串平均长度。后缀树法适用于字符串数量较多的情况,时间复杂度为O(M × N^2),其中N是字符串数量,M是字符串平均长度。哈希表法适用于字符串数量不多且字符串长度不大的情况,时间复杂度为O(M^3 × N),其中N是字符串数量,M是字符串平均长度。根据实际情况选择合适的方法可以提高代码效率。希望本文对你理解和解决多个字符串最长公共子串问题有所帮助。
极客教程