Leetcode-最长回文子串

Leetcode-最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

1. 方法一:暴力查找

直接循环字符串,判断子串是否是回文子串,然后得到最长回文子串;这里用到了字符串方法rfind,也可以直接取当前子字符串直接判断

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        len_str = len(s)
        if len_str <= 1:      #如果输入字符串长度小于等于1,返回字符串本身
            return s
        max_str = ""
        for i in range(len_str):
            for j in range(len_str, i, -1):
                temp = s.rfind(s[i],i+1,j)       #从右往左找第一个s[i],返回序号
                if temp != -1:
                    new_str1 = s[i:(temp+1)]
                    new_str2 = new_str1[::-1]     #[::-1]将数组倒序储存
                    if (new_str1 == new_str2) and (len(new_str1)>len(max_str)):  #判断是否相等且当前子字符串是不是最大
                        max_str = new_str1            
        
        if max_str != "":       #如果没找到max_str,就返回第一个字符串
            return max_str
        else:
            return s[0]
  • 此方法时间复杂度应该是O(n3),超级慢

2. 方法二:中心扩展

遍历字符串,然后判断字符串前后两个字符串是否相等,以此类推。该方法需要根据输入的字符串的奇偶性分别进行查找,为了方便,可以将原字符串间加入“#”,这样只需要遍历一次即可。

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        len_str = len(s)
        if len_str <= 1:
            return s     #如果输入字符串为空或者只有一个,则返回字符串

        max_len = 0
        start_res = 0
        new_str = "#" + "#".join(s) + "#"      #如将字符串“abbc”变为"#a#b#b#c#"
        new_len = len(new_str)
        for i in range(new_len):
            j = i - 1
            k = i + 1
            while j >= 0 and k < new_len and new_str[j] == new_str[k]:
                if k - j + 1 > max_len:
                    max_len = k - j + 1
                    start_res = j
                j -= 1
                k += 1
        if max_len>1:
            return new_str[start_res:start_res + max_len].replace("#",'')   #字符串replace方法,替换原字符串某字符为指定字符
        return s[0]
  • 该方法时间复杂度为O(n2

3.Manacher(马拉车)算法

https://mp.weixin.qq.com/s/RQ_gW8kqLun4_X-kpkqzxg 分享一个非常有意思的马拉车算法解释。
还有这个,https://segmentfault.com/a/1190000003914228

  1. 将原字符串间插入特殊的符号,如方法二
  2. 定义一个数组arr记录每个字符的回文半径
  3. 遍历字符串,求取每个字符串i位置数组对应的回文半径arr[i](如"1536348"6对应的半径为1)。定义一个变量rmax和rpos分别表示当前找到的最右边的回文序号和对应的位置。不断更新rmax和rpos。
class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        len_str = len(s)
        if len_str <= 1:
            return s     #如果输入字符串为空或者只有一个,则返回字符串
        new_str = "#" + "#".join(s) + "#"  #如将字符串“abbc”变为"#a#b#b#c#"
        new_len = len(new_str)
        arr_str = [0] * new_len   #定义一个等长的数组记录每个字符的回文字符个数
        rpos = 0                        #rpos为当前遍历下找到的最右边字符对应的回文对称轴
        rmax = 0                       #rmax为当前遍历下找到的最右边字符对应的序号
        max_pos = 0             #记录最大回文对称轴位置
        max_rad = 0              #记录最大回文对称半径
        for i in range(new_len):
            if i < rmax:
                arr_str[i] = min(arr_str[2 * rpos - i], rmax - i)   #取当前i的对称位置的arr_str,但有右边越界风险,所以跟rmax - i取最小
            else:
                arr_str[i] = 0
            
            while i - arr_str[i] -1 >= 0 and i + arr_str[i]+1 < new_len \
            and new_str[i - arr_str[i]-1] == new_str[i + arr_str[i]+1]:     #找当前i下是否还有其余的回文字符
                arr_str[i] += 1
            if i + arr_str[i] > rmax:                                             #更新rmax、rpos
                rmax = i + arr_str[i]
                rpos = i
            if(arr_str[i] > max_rad):                                       #更新max_rad、max_pos
                max_rad = arr_str[i]
                max_pos = i
 
        return new_str[max_pos-max_rad:max_pos+max_rad+1].replace("#",'')
  • 此方法的时间复杂度O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值