0005_Longest_Palindromic_Substring

0005_Longest_Palindromic_Substring

Posted by taomujian on December 18, 2020

题目

Given a string s, return the longest palindromic substring in s.

找出一个字符串的最大回文子字符串

思路

这道题常见的算法是马拉车算法,但本题解决并没有完全按照马拉车算法来,而是根据马拉车算法进行改善的,二者的区别是马拉车算法要在字符的左右两边都加上辅助字符#,而本答案只是在字符的右边添加了辅助字符#

首先构造辅助字符组成一个数组,然后对这个数组进行轮询,轮询中心点和半径来取中心点的2个元素进行对比,记录位置和半径即可,最后找到半径最大的半径和相应的中心点即可

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env python3

class Solution(object):

    def longestPalindrome(self, s):
        '''
        找出一个字符串的最大长度的回文字符串

        :param str s: 要查找的字符串

        :return str result: 查找到的最大长度回文字符串
        '''
        
        ls = len(s)
        # 如果字符串长度为1或者为0,则结果就是其本身
        if ls <= 1 or len(set(s)) == 1:
            return s
        # 根据马拉车算法扩充字符串,即在字符串右边添加#符号,这并不是完整的马拉车算法,完整的马拉车算法需要在字符的左右两边都要加上#符号
        temp_s = '#'.join('{}'.format(s))

        tls = len(temp_s)
        seed = range(1, tls - 1)

        # 存储最大长度的回文的位置,元素的值是半径,元素的位置是最大长度回文中心点的位置
        len_table = [0] * tls
        # step是检测的半径长度
        for step in range(1, tls // 2 + 1):
            # final是用来存储上一次循环后检测相等的2个元素的中心点,即pos,这样就保证了在step即检测半径增加的时候,中心点pos小于这个半径的左右元素已经是相等的
            final = []
            # pos是中心位置,结合step这个半径来检测中心位置2侧的元素是否相等
            for pos in seed:
                # 如果检测的2个元素数组越界,则跳过
                if pos - step < 0 or pos + step >= tls:
                    continue
                # 如果检测的2个元素不相等,则跳过
                if temp_s[pos - step] != temp_s[pos + step]:
                    continue
                # 如果检测的2个元素相等,则记录其位置
                final.append(pos)
                # 虽然检测的2个元素相等,但是这2个元素是#符号,不记录位置
                if temp_s[pos - step] == '#':
                    continue
                # 检测的2个元素相等,且不是#符号,记录位置
                len_table[pos] = step
            seed = final
            
        max_pos, max_step = 0, 0
        # 找出最大回文的中心点和半径
        for i, s in enumerate(len_table):
            if s >= max_step:
                max_step = s
                max_pos = i
        # 删去#符号
        trans = str.maketrans({key: None for key in '#'})
        return temp_s[max_pos - max_step:max_pos + max_step + 1].translate(trans)

if __name__ == '__main__':
    s = Solution()
    print(s.longestPalindrome("abcbe"))