最长回文子串

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

示例1:

输入‘babad'   输出’bab', 注意aba也是一个有效的答案

输入‘cbbd'  输出’bb'

解题思路:

1.中心扩展算法:遍历每一个索引,以这个索引为中心,利用回文串中心对称的特点,向两边扩散,看最多能扩散多远

也要考虑回文串的奇偶

def spread(s,size,left,right):
    # l=left
    # r=right
    while left>=0 and right<size and s[left]==s[right]:
        left-=1
        right+=1
    return s[left+1:right],right-left-1
def center_spread(s):
    m=len(s)
    if m==0:
        return ''
    logest_len=1
    logest_str=s[0]
    for i in range(m):
        oddstr,oddlen=spread(s,m,i,i)
        evenstr,evenlen=spread(s,m,i,i+1)
        maxstr=oddstr if oddlen>evenlen else evenstr
        if len(maxstr)>logest_len:
            logest_len=len(maxstr)
            logest_str=maxstr
    return logest_str
if __name__=="__main__":
    # s='ababa'
    # s='babad'
    s='cbbbbbdd'
    str=center_spread(s)
    print(str)

2.动态规划算法:用s[i,j]表示在区间[i,j]的字符串,p[i,j]表示s[i,j]是否是回文串,当p[i,j]为true的时候,p[i+1,j-1]也必定为true,那么s[j]与s[i]也相等。其中要保证区间[i+1,j-1]可以形成区间,即i+1<j-1——》j-i>2.

实现细节:因为要构成子串 i一定小于等于 j ,我们只关心 “状态”数组“下三角”的那部分取值。理解上面的“状态转移方程”中的 (i>= j - 2 or p[i+1][j-1]) 这部分是关键。

def dynamiclogest(s):
    size=len(s)
    if size<=1:
        return s
    p=[[False for _ in range(size)]for _ in range(size)]
    longeststr=s[0]
    longest=1
    for j in range(size):
        for i in range(j):
            if s[i]==s[j] and(j-i<=2 or p[i+1][j-1]):
                p[i][j]=True
                if j-i+1>longest:
                    longest=j-i+1
                    longeststr=s[i:j+1]
    return longeststr
if __name__=="__main__":
    # s='ababa'
    # s='babad'
    s='cbbbbbdd'
    str=dynamiclogest(s)
    print(str)

3利用最长公共子串求解:反转 S,使之变成 S' 。找到 SS 和 S'S之间最长的公共子串,这也必然是最长的回文子串。

例如,S = “caba”, S ′ =“abac”:之间的最长公共子串为aba”,恰恰是答案。

当S=“abacdfgdcaba”, S ′=“abacdgfdcaba”:之间的最长公共子串为 “abacd”。显然,这不是回文。

我们可以看到,当 SS 的其他部分中存在非回文子串的反向副本时,最长公共子串法就会失败。为了纠正这一点,每当我们找到最长的公共子串的候选项时,都需要检查子串的索引是否与反向子串的原始索引相同。如果相同,那么我们尝试更新目前为止找到的最长回文子串;如果不是,我们就跳过这个候选项并继续寻找下一个候选。

def longestPalindrome(s):
    s_inverse = s[::-1]
    max = 0
    maxStr = ""
    if len(s) < 2:
        return s
    for start in range(len(s)):
        for end in range(start + 1, len(s) + 1):
            if s.count(s_inverse[start:end]) > 0:
#count()函数是在字符串s中查找符合条件的s_inverse[start:end]字符串的个数
                index = s.index(s_inverse[start:end])
                #index()函数是在字符串s中查找符合条件s_inverse[start:end]的子字符串的首索引位置。
#子串索引index,反向子串索引start_inverse
               # print(index)
                start_inverse = len(s) - end
               # print(start_inverse)
                if (end - start > max) and (index == start_inverse):
                    max = end - start
                    maxStr = s_inverse[start:end]
            #print('******************')
    return maxStr
if __name__=="__main__":
    s='ababa'
    # s='babad'
    str=longestPalindrome(s)
    print(str)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值