我如何加速这段代码?最长回文子串问题
How do I speed up this code? longest palindrome substring problem
我正在研究 Leetcode 问题以找到字符串的最长回文子串。这是我的代码。
def longest_palindrome_substring(string):
array = [i for i in string]
# keep track of which substrings are palindromes
s = [[None for _ in range(len(array))] for _ in range(len(array))]
# longest substring so far
best = ""
# look at successively larger substrings
for substring_length in range(len(array)): # is actually substring length - 1 = stop - start
# look at the substring from start to stop, inclusive
for start, stop in zip(range(len(array) - substring_length), [x + substring_length for x in range(len(array) - substring_length)]):
# is it a palindrome?
if start == stop:
is_p = True
elif array[start] == array[stop]:
if start + 1 == stop:
is_p = True
else:
is_p = s[start + 1][stop - 1]
else:
is_p = False
# store result
s[start][stop] = is_p
# is it the best so far?
if is_p:
if substring_length + 1 > len(best):
best = array[start:stop + 1]
return "".join(best)
我得到了所有的正确答案,但它说这段代码太慢了。我该怎么做才能加快速度?
我正在尝试关注 strategy outlined here。
解决此问题的最有效方法是使用 Manacher 算法求解复杂度为 O(n) 的解决方案,detailed here。
Python 使用 Manacher 算法的代码:https://www.geeksforgeeks.org/manachers-algorithm-linear-time-longest-palindromic-substring-part-3-2/.
对您的代码进行一些分析,概述如下:
================== PerfTool ==================
task |aver(s) |sum(s) |count |std
main loop | 0.863| 0.863| 1| 0.000
+-int loop | 0.001| 0.862| 758| 0.001
+-is_it_pal? | 0.000| 0.092| 287661| 0.000
+-store_res | 0.000| 0.082| 287661| 0.000
init | 0.019| 0.019| 1| 0.000
overall | 0.18| 0.88| 576082|-
如您所见,对于一个长 750 个字符的字符串,总共需要 0.9 秒
在内部。
我的期望是大部分都是零碎的:
# is it a palindrome?
# store result
# is it the best so far?
但事实并非如此,因为他们用了不到 0.2 秒的内部循环 0.8 秒。
所以,主要的时间浪费在这里:
zip(range(len(array) - substring_length), [x + substring_length for x in range(len(array) - substring_length)]):
内部循环的数据准备,耗时0.6s(内部循环的75%)
这是整个算法中效率较低的部分。
时间花费在创建和销毁大量的子字符串上,所以方向是使用另一种数据结构以避免这种影响。
我正在研究 Leetcode 问题以找到字符串的最长回文子串。这是我的代码。
def longest_palindrome_substring(string):
array = [i for i in string]
# keep track of which substrings are palindromes
s = [[None for _ in range(len(array))] for _ in range(len(array))]
# longest substring so far
best = ""
# look at successively larger substrings
for substring_length in range(len(array)): # is actually substring length - 1 = stop - start
# look at the substring from start to stop, inclusive
for start, stop in zip(range(len(array) - substring_length), [x + substring_length for x in range(len(array) - substring_length)]):
# is it a palindrome?
if start == stop:
is_p = True
elif array[start] == array[stop]:
if start + 1 == stop:
is_p = True
else:
is_p = s[start + 1][stop - 1]
else:
is_p = False
# store result
s[start][stop] = is_p
# is it the best so far?
if is_p:
if substring_length + 1 > len(best):
best = array[start:stop + 1]
return "".join(best)
我得到了所有的正确答案,但它说这段代码太慢了。我该怎么做才能加快速度?
我正在尝试关注 strategy outlined here。
解决此问题的最有效方法是使用 Manacher 算法求解复杂度为 O(n) 的解决方案,detailed here。
Python 使用 Manacher 算法的代码:https://www.geeksforgeeks.org/manachers-algorithm-linear-time-longest-palindromic-substring-part-3-2/.
对您的代码进行一些分析,概述如下:
================== PerfTool ==================
task |aver(s) |sum(s) |count |std
main loop | 0.863| 0.863| 1| 0.000
+-int loop | 0.001| 0.862| 758| 0.001
+-is_it_pal? | 0.000| 0.092| 287661| 0.000
+-store_res | 0.000| 0.082| 287661| 0.000
init | 0.019| 0.019| 1| 0.000
overall | 0.18| 0.88| 576082|-
如您所见,对于一个长 750 个字符的字符串,总共需要 0.9 秒 在内部。 我的期望是大部分都是零碎的:
# is it a palindrome?
# store result
# is it the best so far?
但事实并非如此,因为他们用了不到 0.2 秒的内部循环 0.8 秒。
所以,主要的时间浪费在这里:
zip(range(len(array) - substring_length), [x + substring_length for x in range(len(array) - substring_length)]):
内部循环的数据准备,耗时0.6s(内部循环的75%) 这是整个算法中效率较低的部分。 时间花费在创建和销毁大量的子字符串上,所以方向是使用另一种数据结构以避免这种影响。