5:最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
一、法一暴力破解
这个就不用多解释了
class Solution {
/**
* 法一:
* @param String $s
* @return String
*/
function longestPalindrome($s) {
$len = strlen($s);
$tmps = '';
$max = 0;
for($i=0 ; $i<$len; $i++){ //起始下标
for($j=$i+1; $j<=$len;$j++){ //长度
if($this->isPalindrome(substr($s,$i,$j)) && $j > $max){
$tmps = substr($s,$i,$j);
$max = $j;
}
}
}
return $tmps;
}
function isPalindrome($subs){
$len = strlen($subs);
for($i=0; $i<(int)($len/2); $i++){
if($subs[$i] != $subs[$len-$i-1]){
return false;
}
}
return true;
}
}
二、最长公共子串
思路:就是把字符串反转过来,例如 s=‘ababc’,反正s‘=’cbaba‘,两个字符串左右重合,得出最长的子串就是答案,也就是bab(或aba)。但是有可能会出现==特例(如:S = abc435cba,S' = abc534cba)==,重合,子串为abc。不符合条件,需要加判断
class Solution2 {
/**
* @param String $s
* @return String
*/
function longestPalindrome($s) {
$len = strlen($s);
if($len == ''){
return $s;
}
$origin = $s;
$reverse = strrev($s);
$arr = [];
$maxLen = 0;
$maxStart = 0;
for($i=0; $i<$len; $i++){//原始字符串下标
for($j=0; $j<$len; $j++){ //倒置后字符串下标
if($origin[$i] == $reverse[$j]){
if($i == 0 || $j ==0){
$arr[$i][$j] = 1;
}else{
//状态转移方程
$arr[$i][$j] = $arr[$i-1][$j-1] + 1;
}
/**
* 用来规避特殊情况
* 如:S = abc435cba,S' = abc534cba
* 不特殊处理,abc 会被判断为最小回文子串
* 解:判断倒置前的子串下标,是否符合条件
*/
if($arr[$i][$j] > $maxLen){
$beforeJ = $len - $j - 1;
if($beforeJ + $arr[$i][$j] -1 == $i){
$maxLen = $arr[$i][$j];
$maxStart = $i;
}
}
}else{
$arr[$i][$j] = 0;
}
}
}
echo substr($s,$maxStart-$maxLen+1,$maxLen);
}
}
三、中心拓展法
把每个字母当成回文串的中心。考虑两种情况,长度为奇数和偶数
class Solution3 {
/**
* @param String $s
* @return String
*/
function longestPalindrome($s) {
$n = strlen($s);
if($n == ''){
return $s;
}
$start = 0;
$maxlen = 0;
for($i=0; $i<$n; $i++){
$len1 = $this->isPalindrome($s,$i,$i);//奇数
$len2 = $this->isPalindrome($s,$i,$i+1);//偶数
$len = max($len1,$len2);
if($len > $maxlen){
$start = $i - ($len-1)/2;
$maxlen = $len;
}
}
return substr($s,$start,$len) ;
}
function expend($str,$i,$j){
$n = strlen($str);
$l = $i;
$r = $j;
while($l>=0 && $r<$n && $str[$l] == $str[$r]){
$l-- ;
$r++ ;
}
return $r-$l-1;
}
}
三、马拉车算法
重新组合字符串,将其变为奇数个。充分的利用回文串的对称性质,
class Solution4 {
/**
* @param String $s
* @return String
*/
function longestPalindrome($s) {
$T = $this->malache($s);
$n = strlen($T);
$C = $R = 0;
$p = [];
for($i=1; $i<$n-1; $i++){
$i_mirror = $C*2 - $i;
if($R>$i){
$p[$i] = min($R-$i,$p[$i_mirror]);
}else{
$p[$i] = 0;
}
while(($T[$i-1-$p[$i]]) == ($T[$i+1+$p[$i]]) ){
$p[$i]++;
}
if($i + $p[$i] > $R) {
$C = $i;
$R = $i + $p[$i];
}
}
$maxLen = 0;
$centerIndex = 0;
for ($i=1; $i<$n-1;$i++ ){
if($p[$i] > $maxLen){
$maxLen = $p[$i];
$centerIndex = $i;
}
}
$start = ($centerIndex-$maxLen)/2;
echo substr($s,$start,$maxLen);
}
function malache($str){
$n = strlen($str);
if(!$str){
return "^$";
}
$ret = '^';
for($i=0; $i<$n; $i++){
$ret .= '#'.$str[$i];
}
$ret .= "#$";
return $ret;
}
}