返回
多维视角,深入理解LeetCode 2213题:揭秘重复字符串的妙解奥秘
后端
2023-11-01 00:54:45
在LeetCode的挑战之旅中,2213题"由单个字符重复的最长子字符串"以其困难度吸引着无数算法爱好者。本文将从多个角度深入理解此题,为您揭示解决问题的奥秘。让我们共同开启这场探索算法之美的旅程!
问题陈述:
给定一个字符串s,你需要找出其中最长的由单个字符重复构成的子字符串的长度。
方法一:线段树
- 构建一棵线段树,区间节点记录区间内相同字符的重复次数。
- 从左到右遍历字符串,不断更新线段树上的区间节点值。
- 在更新过程中,通过查询线段树获取当前区间内相同字符的最大重复次数,从而求得最长的重复子字符串长度。
方法二:动态规划
- 定义dp[i]表示以字符串s的第i个字符为结尾的最长重复子字符串的长度。
- 递推关系:dp[i] = dp[i-1] + 1 (s[i] == s[i-1])
- 最终结果为max(dp[1], dp[2], ..., dp[n])
方法三:KMP算法
- KMP算法是一种字符串匹配算法,也可以用于解决这个问题。
- 构建失配表next[i],表示当模式串与文本串匹配到第i个字符时,模式串中下一个要匹配的字符的下标。
- 利用next表,当模式串与文本串匹配到第i个字符时,若不匹配,则将模式串的匹配位置回溯到next[i]处继续匹配。
- 在匹配过程中,当模式串与文本串完全匹配时,则更新最长重复子字符串长度。
代码实现:
方法一:线段树
import sys
class SegmentTree:
def __init__(self, arr):
self.n = len(arr)
self.tree = [0] * (4 * self.n)
self.build(arr, 1, 0, self.n - 1)
def build(self, arr, node, start, end):
if start == end:
self.tree[node] = 1
return
mid = (start + end) // 2
self.build(arr, 2 * node, start, mid)
self.build(arr, 2 * node + 1, mid + 1, end)
self.tree[node] = max(self.tree[2 * node], self.tree[2 * node + 1])
def query(self, node, start, end, l, r):
if l > end or r < start:
return 0
if l <= start and r >= end:
return self.tree[node]
mid = (start + end) // 2
left = self.query(2 * node, start, mid, l, r)
right = self.query(2 * node + 1, mid + 1, end, l, r)
return max(left, right)
def longest_repeating_substring(s):
tree = SegmentTree([0] * len(s))
max_len = 0
for i in range(len(s)):
for j in range(i):
if s[i] == s[j]:
max_len = max(max_len, tree.query(1, 0, len(s) - 1, j + 1, i) + 1)
tree.update(i, 1)
return max_len
# 测试
s = "abbaba"
print(longest_repeating_substring(s)) # 3
方法二:动态规划
def longest_repeating_substring(s):
dp = [0] * len(s)
max_len = 0
for i in range(1, len(s)):
if s[i] == s[i - 1]:
dp[i] = dp[i - 1] + 1
max_len = max(max_len, dp[i])
return max_len
# 测试
s = "abbaba"
print(longest_repeating_substring(s)) # 3
方法三:KMP算法
def longest_repeating_substring(s):
n = len(s)
next = [0] * n
# 构建next表
i, j = 1, 0
while i < n:
if s[i] == s[j]:
j += 1
next[i] = j
i += 1
else:
if j > 0:
j = next[j - 1]
else:
next[i] = 0
i += 1
# 利用next表匹配字符串
i, j, max_len = 0, 0, 0
while i < n:
if s[i] == s[j]:
j += 1
max_len = max(max_len, j)
i += 1
else:
if j > 0:
j = next[j - 1]
else:
i += 1
return max_len
# 测试
s = "abbaba"
print(longest_repeating_substring(s)) # 3
结论:
我们通过LeetCode的2213题深入探究了线段树、动态规划和KMP算法在重复字符串问题中的运用。这些算法各有优缺点,选择合适的方法取决于具体问题的情况。希望这篇文章对您理解这些算法及其应用有所帮助。