[动态规划] 六、最长回文子串

题目

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:输入: “ABCDDCEFA”。输出: “CDDC”。
回文子串就是一个字符串从左到右读和从右到左读是完全一样的,比如 “a”、“aba”、“abba”。
条件
字符串:ABCDDCEFA

动态规划问题建模阶段

i是终止字符,j是起始字符

i结束\j开始 0 1 2 3 4 5 6 7 8
0 1
1 0 1
2 0 0 1
3 0 0 0 1
4 0 0 0 1 1
5 0 0 1 0 0 1
6 0 0 0 0 0 0 1
7 0 0 0 0 0 0 0 1
8 0 0 0 0 0 0 0 0 1
规律:
d[0][0] = 1
d[4][3] = 1  表示字符串从str[3]到str[4] = DD
d[5][2] = 1  表示字符串从str[2]到str[5] = CDDC

由此可见,当子串两端的字符str[i]=str[j]时,再判断去掉两端字符的子串d[i-1][j+1]是否是回文。
如果是回文,即d[i-1][j+1]=1,则d[i][j]是回文

动态规划三个重要的概念

最优子结构:
当str[8]=str[0]时,判断d[7][1],即从str[1]到str[7]是否是回文

边界:
d[0][0] = 1
转态转移公式:
d[i][j] = 1 , i-j<3, str[i]=str[j] 因为小于3个字符一定是回文,例 A、AA、ABA
d[i][j] = d[i-1][j+1] , i-j>3, str[i]=str[j]

动态规划求解问题阶段

<?php

namespace app\index\controller;

class Index 
{
    /**
     * 动态规划(Dynamic Programming)
     * 时间复杂度:O(n²)
     * 空间复杂度:O(n²)
     */
    public function test()
    {
        $str        = 'babad';
        $palindrome = [];         // 存储“起始字符到终止字符”是否是回文,1是,0否
        $max_len    = 1;          // 存储最长回文子串长度
        $start_char = 0;          // 存储最长回文子串的起始位置
        $str_len    = strlen($str);

        // 循环字符串, i是终止字符
        for ($i=0; $i<$str_len;$i++) {

            // 循环i终止字符的每种长度情况,j是起始字符
            for ($j=0;$j<$i;$j++) {

                // 先赋初始值,供后面判断 $max_len 时使用
                $palindrome[$i][$j] = 0;

                // 字符串两头相等,根据三种情况判断是否为回文
                if ($str[$i] == $str[$j]) {
                    // 情况一:如果只有一个字符:i-j = 0;(例 A) 在数组对角线,值全为1,可写可不写
                    // 情况二:如果有两个字符:  i-j = 1;(例 AA)
                    // 情况三:如果有三个字符:  i-j = 2;(例 ABA)
                    // 这三种情况都为回文
                    if ($i-$j < 3) {
                        $palindrome[$i][$j] = 1;
                    } else {
                        // 情况四:如果子串长度大于3,判断$palindrome[i-1][j+1] 是否为1。(去两端的字符串)
                        if ($palindrome[$i-1][$j+1]) {
                            $palindrome[$i][$j] = 1;
                        }
                    }

                    // 如果是回文,且其长度比$max_len大,则更新$max_len值
                    if ($i-$j+1>$max_len && $palindrome[$i][$j]) {
                        $max_len = $i-$j+1;
                        $start_char = $j;
                    }
                }
            }
        }
        echo $max_len . "</br>";
        echo $start_char;
    }
}

参考:最长回文子串

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!