leetcode--最长回文字符串

背景; 求解字符串最长回文长度。
尝试方法: 暴力遍历,马拉车(中心扩散法)

# -*- coding: utf-8 -*-
"""
Created on Tue Mar 17 19:55:45 2020

@author: Administrator
"""


    ## 回文串是连续的子串,从左读和从右读顺序一样
class Solution(object):
    
    """暴力方法:遍历所有子串比较繁琐"""
    ## 初始版本, 太多多余定义
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        m=0 # 当前子串初始长度
        max_len=0  #最大回文子串初始长度
        max_plaind=''
        for i in range(len(s)):
            m=i+1 ##当前子串的长度
            str1='' ## 当前子串
            flag=0
            for j in range(len(s)):
                if m<=len(s) and (j+m<=len(s)): ##子串长度不能大于最长,子串右边位置不能超过边界
                    str1=s[j:j+m] ## 当前子串
                    if str1==str1[:: -1]: ## 判断正读和反读是否一样
                        flag=1  
                    if flag==1 and len(str1)>max_len:
                        max_len=len(str1)
                        max_plaind=str1
                else:
                    break    
        return max_plaind
    
    
    """ 暴力方法: 代码缩减后,第一层子串个数,第二层子串开始位置"""
    def longestPalindrome1(s):
        """
        :type s: str
        :rtype: str
        """
        m=0 # 当前子串初始长度
        max_len=0  #最大回文子串初始长度
        max_plaind=''
        if s==s[:: -1]:
            return s
        for i in range(len(s)-1):
            m=i+1
            for j in range(len(s)-m+1):
                print str(m)+' '+str(j+m)+' '+ s[j:j+m]+' '+s[j:j+m][::-1]
                if m>max_len and j+m<=len(s) and s[j:j+m]==s[j:j+m][::-1]: ##子串长度不能大于最长,子串右边位置不能超过边界
                        max_len=m
                        max_plaind=s[j:j+m]
        return max_plaind
        
        

    """ 暴力方法: 代码缩减后,第一层,子串开始位置, 第二层,子串长度"""
    ## 注意切片时得+1,因为n:m, 实际取的是n:m-1
    def otheran(s):
        max_len=1 ##最大回文子串长度
        max_plaind='' # 最大回文子串
       
        if s==s[::-1]:
            return s
        else:
            for i in range(len(s)-1):
                for j in range(i+1,len(s)):
                    if j-i>max_len and s[i:j+1]==s[i:j+1][::-1]:
                        max_len=j-i
                        max_plaind=s[i:j+1]
            return max_plaind
                     
        
     
    """马拉车--Manacher算法,参考别人的"""
       ##这是一个复杂度为 O(n) 的 Manacher(马拉车) 算法。
       ##假如字符串是奇数个,那么我们可以通过遍历所有字符串,再对所有字符串进行左右匹配,就像中心扩散方法一样。然后得到长度最大的字符串
       ##但是如果字符串是偶数个,我们无法进行此操作
       ##这个算法的最终要的额一点就是,我们将一个偶数长/奇数长的字符串,构造成新的字符串。
       ##这样我们可以对新字符串的每个字符,进行左右匹配。
       
       ##以每个字符为中心,开始向两边按step=1,向两边扩充,下次迭代条件,左右都没有越界,且左右相等。
       ##其次,每次扩充后新的回文与旧回文做比较,更新最大回文字符串。
     
      ## 回文字符串起始位置 start=(i-max_len)//2 ,其中,i表示当前中心所在位置
       
    def manacherTest(s):        
        if str(len(s))<2:
            return s
        max_len=0
        
        """因为要想中心扩散,字符串是奇数可以中心扩散,但是偶数的话不能中心扩散,因此对字符串做处理"""
        test="#"+"#".join(s)+'#' ## 奇数需要偶数个填充,偶数需要奇数个填充
        
        """以第二个字符开始,因为第一个左边是空的,不需要扩散"""
        for i in range(len(test)):
            left=i-1 # 左扩散
            right=i+1 #右扩散
            step=0 ## 初始化步长
            
            """以i为中心开始扩散,扩散条件,等步长扩散后,左右不越界,且左边等于右边"""
            #print("spread",'i='+str(i),'left:'+test[left],test[i],'right:'+test[right],left,right)
            while left>=0 and rightmax_len:
                max_len=step
                start=(i-max_len)//2 ##确定起始位置, '//'向下取整 (i-max_len)//2,减去回文得到回文起始位置,再除2,得到起始位置
                print(i,step)  
        return s[start:start+max_len]

你可能感兴趣的:(leetcode)