美文网首页
leetcode-5. 最长回文子串

leetcode-5. 最长回文子串

作者: 简简天天 | 来源:发表于2020-04-05 18:39 被阅读0次

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"

解题思路一:中心扩展算法

1.回文是一个正读和反读都相同的字符串
2.回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 1 个这样的中心。
3.为什么会是 2n - 1 个,而不是 n 个中心?比如有字符串abcba,这时回文子串是abcda,中心是c;又有字符串adccda,这时回文子串是adccda,中心是cc。 由此可见中心点既有可能是一个字符,也有可能是两个字符,当中心为一个字符的时候有n个中心,当中心为两个字符的时候有n-1个中心,所以一共有2n-1个中心。
4.然后for循环开始从左到右遍历,为什么会有两次 expandAroundCenter,一次是i和i本身,一次是i和i+1,这就是上面说到的一个中心与两个中心。
5.而后会去判断这两种情况下谁的回文子串最长,并标记出这个子串在原字符串中的定位,即start和end。

<?php

class Solution
{
    /**
     * 获取最长回文子串
     * @param $str
     * @return false|string
     */
    public function longestPalindrome($str)
    {
        if ($str == null || strlen($str) < 1) return "";
        $start = 0; // 最大回文子串起始下标
        $end = 0;// 最大回文子串结束下标
        for ($i = 0; $i < strlen($str); $i++) {
            $len1 = $this->expandAroundCenter($str, $i, $i);//单个字符为中心
            $len2 = $this->expandAroundCenter($str, $i, $i + 1);//两个字符为中心
            $len = max($len1, $len2);//获取两者最长子串
            if ($len > $end - $start) {//调整起始和结束下标
                $start = $i - intval(($len - 1) / 2);
                $end = $i + intval($len / 2);
            }
        }
        return substr($str, $start, $end - $start + 1);
    }

    /**
     * 获取以left right为中心的回文字段长度
     * @param $str
     * @param $left
     * @param $right
     * @return int 回文子串的长度
     */
    private function expandAroundCenter($str, $left, $right)
    {
        while ($left >= 0 && $right < strlen($str
            ) && $str[$left] == $str[$right]) {
            $left--;
            $right++;
        }
        return $right - $left - 1;
    }

}
$solution = new Solution();
$str = 'cbbd';
echo ($solution->longestPalindrome($str)) . PHP_EOL;
$str = 'cbabcd';
echo ($solution->longestPalindrome($str)) . PHP_EOL;
bb
cbabc

时间复杂度:O(n^2)
空间复杂度:O(1)

解题思路二:最长公共子串

根据回文串的定义,正着和反着读一样,那我们是不是把原来的字符串倒置了,然后找最长的公共子串就可以了。例如 S = "caba" ,S = "abac",最长公共子串是 "aba",所以原字符串的最长回文串就是 "aba"。

关于求最长公共子串(不是公共子序列),有很多方法,这里用动态规划的方法,整体思想就是,申请一个二维的数组初始化为 0,然后判断对应的字符是否相等,相等的话arr [ i ][ j ] = arr [ i - 1 ][ j - 1] + 1。当 i = 0 或者 j = 0 的时候单独分析,字符相等的话 arr [ i ][ j ] 就赋为 1 。
arr [ i ][ j ] 保存的就是公共子串的长度。


image.png
image.png
<?php
error_reporting('EALL & Notice');

class Solution
{
    /**
     * 获取最长回文子串
     * @param $str
     * @return false|string
     */
    public function longestPalindrome($str)
    {
        $len = strlen($str);
        if ($str == null || $len < 1) return "";
        $reverse = strrev($str);
        $maxLen = 0;// 最大回文子串长度
        $maxEnd = 0;// 最大回文子串结束下标
        $arr = array(array());
        for ($i = 0; $i < $len; $i++) {
            for ($j = 0; $j < $len; $j++) {
                if ($str[$i] == $reverse[$j]) {
                    if ($i == 0 || $j == 0) {
                        $arr[$i][$j] = 1;
                    } else {
                        $arr[$i][$j] = $arr[$i - 1][$j - 1] + 1;
                    }
                }
                if ($arr[$i][$j] > $maxLen) {
                    $beforeRev = $len - $j - 1;// 反转前起始下标
                    if($beforeRev + $arr[$i][$j] - 1 == $i){//判断下标是否对应
                        $maxLen = $arr[$i][$j];
                        $maxEnd = $i;

                    }

                }

            }

        }
        return substr($str, $maxEnd - $maxLen + 1, $maxLen);
    }

}

$solution = new Solution();
$str = 'cbb';
echo ($solution->longestPalindrome($str)) . PHP_EOL;
$str = 'cbabcd';
echo ($solution->longestPalindrome($str)) . PHP_EOL;
$str = 'abc43cba';
echo ($solution->longestPalindrome($str)) . PHP_EOL;
结果:
bb
cbabc
a

时间复杂度:两层循环 O(n²)。
空间复杂度:一个二维数组 O(n²)。

相关文章

  • leetcode-5. 最长回文子串

    给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。示例 1:输入: "bab...

  • LeetCode-5. 最长回文子串

    题目 描述 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1: ...

  • 最长回文子串

    最长回文子串——Manacher 算法 1. 问题定义 最长回文字符串问题:给定一个字符串,求它的最长回文子串长度...

  • 字符串算法

    最长公共前缀 最长回文串 最长回文子序列 最长公共子串 反转单词顺序列 反转字符串 字符串转数字 IP-int互转

  • 打卡-最长回文子串

    最长回文子串(中等)

  • 最长回文子序列

    该问题区别于最长回文子串,子串必须是连续的,而子序列则可以跳跃,例如AABCAA的最长回文子串为AA,但是它的最长...

  • Manacher算法

    最长回文子串问题# 给定一个字符串,找出最长的回文子串,如"waabwswbfd",则最长子串为bwsb. 中心试...

  • 最长回文子串问题—Manacher算法

    最长回文串问题是一个经典的算法题。 0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度。如果...

  • LeetCode 第647题:回文子串

    1、前言 2、思路 此题与最长回文子串很像,只不过那个是求最长的回文子串,而这个是求回文子串的数目。但是他们的解法...

  • C语言实现求最长回文子串

    最长回文子串的概念 回文串是指正序和反序都一样的字符串,例如:Str1 = "AbbA",则Str1的最长回文子串...

网友评论

      本文标题:leetcode-5. 最长回文子串

      本文链接:https://www.haomeiwen.com/subject/pycuphtx.html