最长回文子串(python)

又开始刷题了,去年被这道题虐过,今天终于写了一个还能看的版本。

这个版本肯定不是最优,这篇博客主要记录一下解题的过程,反思如何构思代码。

最长回文子串

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/longest-palindromic-substring

难度:中等(我觉得这题完全配得上困难)

题目:

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

示例 1:

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

输入: "cbbd"
输出: "bb"

解题过程

看到这题一开始是完全懵逼的,看着两个例子想了一个错的解法:用两个指针指向字符串的首尾,当两个指针所指的内容相同时,记录下两个索引值,不同时索引值归零,直到两个指针相遇。

这个解法很明显是错的,因为它假定了最长回文子串的中心一定是字符串中心

这个时候我看到了题目的三条提示:

How can we reuse a previously computed palindrome to compute a larger palindrome?

If “aba” is a palindrome, is “xabax” and palindrome? Similarly is “xabay” a palindrome?

Complexity based hint:
If we use brute-force and check whether for every start and end position a substring is a palindrome we have O(n^2) start - end pairs and O(n) palindromic checks. Can we reduce the time for palindromic checks to O(1) by reusing some previous computation.

前两条提示非常有用,我想到回文的特征是:呈中心对称。即,两个指针以同样的步幅从回文的中心出发,所指内容应该会一直保持一致。应该还是使用两个指针,但是是从内到外走,而不是从外到内

总体算法思路为:遍历整个字符串,将每个位置当作回文中心去找以这个字符为中心能形成的最长回文,然后选出整个字符串最长的回文

这里有一个很干扰我思路的问题出现了:就是‘cbbd‘这种情况。我的算法是无法输出‘bb‘的,在这个地方卡了很久。后来我决定把这种情况特殊处理,如果第i个字符串与第i+1个字符串相同,则将尾指针往后移。

我觉得有一个经验就是,在时间紧迫的时候,先把自己能想出来的完整算法写出来,再想办法去处理特殊情况,否则在那空想是很浪费时间的。

第一版:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        longest_palindrome = {'length': 0, 'str': ''}
        for i in range(n):
            index1 = index2 = i
            if i+1 < n and s[i+1] == s[i]:
                index1 = i
                index2 = i+1
            while index1-1 >= 0 and index2+1 < n and s[index1-1] == s[index2+1]:
                index1 += -1
                index2 += 1
            length = index2 - index1 + 1
            if length > longest_palindrome['length']:
                longest_palindrome['length'] = length
                longest_palindrome['str'] = s[index1:index2+1]
        return longest_palindrome['str']

结果:不通过

不通过的用例:

输入:
"ccc"
输出:
"cc"
预期:
"ccc"

在第二个c的位置,由于第三个c与第二个c相等,则index1=1,index2=2,将回文的中心变成了这两个字符,所以出错。

解决的思路是:找全所有所有相同的字符组成一个回文中心,即在处理第一个c的时候,就一直往后找,直到回文中心变为"ccc"

第二版:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        longest_palindrome = {'length': 0, 'str': ''}
        for i in range(n):
            index1 = index2 = i
            while index2+1 < n and s[index1] == s[index2+1]:
                index2 += 1
            while index1-1 >= 0 and index2+1 < n and s[index1-1] == s[index2+1]:
                index1 += -1
                index2 += 1
            length = index2 - index1 + 1
            if length > longest_palindrome['length']:
                longest_palindrome['length'] = length
                longest_palindrome['str'] = s[index1:index2+1]
        return longest_palindrome['str']

通过是通过了。就是执行时间980ms,位于前32%不太满意。可以再优化一下,不要每次找到更长的回文就切出来,只需要记下索引就好了

第三版:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        l_len = 0
        l_index1 = 0
        l_index2 = 0
        for i in range(n):
            index1 = index2 = i
            while index2+1 < n and s[index1] == s[index2+1]:
                index2 += 1
            while index1-1 >= 0 and index2+1 < n and s[index1-1] == s[index2+1]:
                index1 += -1
                index2 += 1
            length = index2 - index1 + 1
            if length > l_len:
                l_len = length
                l_index1 = index1
                l_index2 = index2
        return s[l_index1: l_index2+1]

执行时间优化至852ms,位于前26%。就这样吧,三个小时已经过去了,写算法题并不是写业务逻辑,性能比易读性更重要

原文地址:https://www.cnblogs.com/luozx207/p/12177741.html

时间: 2024-08-30 16:09:57

最长回文子串(python)的相关文章

leetcode 5 :Longest Palindromic Substring 找出最长回文子串

题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 翻译: 找出字符串s中最长的回文子串,字符串s的最长是1000,假设存在唯一的最长回文子串 法一:直接暴力破解 O(N3)的时间复杂度,运行超

Manacher&#39;s algorithm: 最长回文子串算法

Manacher 算法是时间.空间复杂度都为 O(n) 的解决 Longest palindromic substring(最长回文子串)的算法.回文串是中心对称的串,比如 'abcba'.'abccba'.那么最长回文子串顾名思义,就是求一个序列中的子串中,最长的回文串.本文最后用 Python 实现算法,为了方便理解,文中出现的数学式也采用 py 的记法. 在 leetcode 上用时间复杂度 O(n**2).空间复杂度 O(1) 的算法做完这道题之后,搜了一下发现有 O(n) 的算法.可惜

《算法竞赛入门经典》3.3最长回文子串

1 //例题3-4 2 /* 3 * 输入一个字符串,求出其中最长的回文子串.子串的含义是:在原串中连续出现的字符串片段. 4 *回文的含义是:正看着和倒看着相同,如abba和yyxyy.在判断时,应该忽略所有标点符号和空格 5 *且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符).输入字符长度不超过5000 6 *且占据单独的一行.应该输出最长回文串,如果有多个,输出起始位置最靠左的. 7 *样例输入:Confuciuss say:Madam,I'm Adam. 8 *样例

Manacher算法----最长回文子串

题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些的子串,那么对子串的回文判断其实是不需要的.同时,奇数和偶数长度还要分别考虑. Manacher算法可以解决上述问题,并在O(n)时间复杂度内求出结果.下面我们来看一下Manacher算法. 首先,为了处理奇偶的问题,在每个字符的两边都插入一个特殊的符号,这样所有的奇数或偶数长度都转换为奇数长度.比

hihocoder1302 最长回文子串

hihocoder1302 最长回文子串 先贴代码 所有的上面的提示已经交代的好清楚了…… #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <queue> #include <sta

[hiho 01]最长回文子串、Manacher算法

题目描述 - 基础方法:枚举子串,判断是否为回文串. - 改进:枚举中间位置,向两侧拓展. - 再改进:利用以前的信息,使得不用每个新位置都从长度1开始拓展. - 优化:将字符串预处理为奇数长度以避免考虑条件分支. - 再优化:开头加入特殊字符避免考虑边界. Manacher 算法: id 是中心点,mx 是其边界.P[i] 表示以 i 为中心的最长回文子串的折半长度. 只要 i < mx, 以 i 为中心的回文子串就可以不必从长度1开始找,而从min{P[j], mx - i}开始(其中j为i

[C++]LeetCode: 99 Longest Palindromic Substring (最长回文子串)

题目:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 思路:题目要求的s的一个最长回文子串.暴力解决办法就是枚举所有的子串,再对每个子串进行回文判断.进行剪枝,我们考虑可以使用动态规划来避免重复的判

[译]最长回文子串(Longest Palindromic Substring) Part II

[译+改]最长回文子串(Longest Palindromic Substring) Part II 问题:给定字符串S,求S中的最长回文子串. 在上一篇,我们给出了4种算法,其中包括一个O(N2)时间O(1)空间的算法(中心检测法),已经很不错了.本篇将讨论一个O(N)时间O(N)空间的算法,即著名的Manacher算法,并详细说明其时间复杂度为何是O(N). 提示 +BIT祝威+悄悄在此留下版了个权的信息说: 先想想有什么办法能改进中心检测法. 考虑一下最坏的情况.★ 最坏的情况就是各个回文

URAL 1297 后缀数组:求最长回文子串

思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. 然后看题解,里面都是用RMQ先预处理任意两个后缀的最长公共前缀,因为不太知道这个,所以又看了一下午,嘛嘛-- 然后理解RMQ和后缀一起用的时候才发现其实这里不用RMQ也可以,只要特殊处理一下上面这个没过的例子就行了,哈哈--机智-- 不过那个国家集训队论文里面正解是用RMQ做的,自己还得会和RMQ一