运用马拉车算法求字符串的最长子串

对于最长回文子串,使用其镜像性可以达到一时间复杂度为o(n)的算法。
1.首先对于字符串,无论长度为奇数或偶数,经过相邻两位之间添加未在串中出现的如“#”类字符(为了避免越界首尾也要添加),然后再在首位和尾部添加不同于#和串内字符的两种字符^和$,使其长度均变为奇数。
2.之后对于新字符串S,假设目前所知道的最长的字符串中心为center,边界分别为LEFT和RIGHT,目前搜索到的为第i位。
新建一个长度等于S的数组P=[0]*len(s) 用于表示i位的回文最长半径,之后可进行如下判断:
1.RIGHT>=i:
由于回文串的镜像性,i在center左边,LEFT右边有一个对应下标j=2center-i,且对于i和j到边界LEFT,RIGHT的长度相同,之后可进行第二次分类:
A.i+p[i]<=RIGHT
B.i+p[i]>RIGHT
均满足p[i]=min(p[j],RIGHT-i)
2.RIGHT<i:
P[i]=0
之后对于情况B以及2的情况,只需要继续进行RIGHT外的比较,可采用while循环,满足条件时 半径加一。
之后将中心定为i,右边界定为p[i]+I。
3.最后只需要采用循环寻找出最大的半径以及其中心,然后计算出起始点,由于之前阔倍的原因,起始点为MAX_I-1-p[MAX_I],由于p[i]为扩充后的半径,正好是子串的长度。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        l=len(s)
        
        t='^'
        center,right=0,0
        if s=='' or len(s)==1:
            return s
        for c in s:
            t=t+'#'+c
        t=t+'#'+'$'
        p=[0]*len(t)
        for i in range(1,len(t)-1):
            j=2*center-i
            if right>i:
                p[i]=min(right-i,p[j])
            else:
                p[i]=0
            while(t[i-1-p[i]]==t[i+1+p[i]]):
                p[i]+=1
            if right<i+p[i]:
                center=i
                right=i+p[i]
        max_i=0
        for i in range(1,len(t)-1):
            if p[i]>p[max_i]:
                max_i=i
        start = round((max_i-1-p[max_i])/2)
        return s[start:start+p[max_i]]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值