📅  最后修改于: 2023-12-03 15:40:42.670000             🧑  作者: Mango
这是一个可以找出没有两个相邻字母相同的元音的最长子串的算法。元音字母是指英语中的 a、e、i、o、u 这五个字母。该算法使用了动态规划的思想,时间复杂度为 O(n),空间复杂度为 O(n),效率较高。
dp
和 pre
,dp[i]
表示以第 i 个字母结尾的最长子串长度,并且第 i 个字母为元音字母;pre[i]
表示以第 i 个字母结尾的最长子串的上一个元音字母的下标。dp[i]
和 pre[i]
均为 0;
b. 如果第 i 个字母是元音字母,则:
i. 如果前面没有元音字母,那么 dp[i] = 1
,pre[i] = -1
;
ii. 如果前面有元音字母,那么 dp[i] = dp[i-1] + 1
,pre[i] = j
,其中 j
是前面最近的一个元音字母的下标。dp
数组中的最大值,即为没有两个相邻字母相同的元音的最长子串的长度。通过 pre
数组可以还原出该子串。def longest_substring(s: str) -> str:
vowels = {'a', 'e', 'i', 'o', 'u'}
dp = [0] * len(s) # dp[i] 表示以第 i 个字母结尾的最长子串长度,并且第 i 个字母为元音字母
pre = [-1] * len(s) # pre[i] 表示以第 i 个字母结尾的最长子串的上一个元音字母的下标
max_len = 0 # 最长子串的长度
end = 0 # 最长子串的结尾位置
for i in range(len(s)):
if s[i] not in vowels:
dp[i], pre[i] = 0, -1
else:
if i == 0: # 特殊处理第一个元音字母
dp[i], pre[i] = 1, -1
else:
if s[i - 1] in vowels: # 检查前面是否有元音字母
pre[i] = pre[i - 1]
else:
pre[i] = i - 1
dp[i] = i - pre[i]
if dp[i] > max_len:
max_len, end = dp[i], i
start = end - max_len + 1 # 最长子串的起始位置
return s[start:end+1]
assert longest_substring('leetcode') == 'od'
assert longest_substring('abcdeaicduo') == 'aecduo'