最長迴文子串
迴文串(palindromic string)是指這個字符串無論從左讀還是從右讀,所讀的順序是一樣的;簡而言之,迴文串是左右對稱的。所謂最長迴文子串問題,是指對於一個給定的母串,找到的一個子串,是迴文串,並且長度最長
1、題目描述
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
給定一個字符串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度爲1000。
示例 1:
輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。
示例 2:
輸入: "cbbd"
輸出: "bb"
2、解題思路
2.1 窮舉法
從字符串的左側,依次開始掃描,使用雙重循環,將所有的子串得到,然後判斷子串是否是迴文串,如果是,判斷長度是否是最長的,是最長的,就更新長度,並記錄這個字串
不過需要分奇偶進行判斷
2.2 動態規劃
動態規劃的思路就是,利用前面的結果進行判斷,例如
如上所示,i和j表示下標,i在前,j在後,因此,判斷的時候,如果判斷到當前的是否是迴文串,可以利用前面的結果來判斷是不是迴文串,比起前面構造的窮舉法,少了一層循環
2.3 分治法
考慮迴文串中間部分是相同的,從母串的每一個字符入手,向左右判斷迴文串的長度
2.4 Manacher
這個算法主要思想集中在將奇偶數的判斷放在一起
例如下面的字符串
abcde
變成
#a#b#c#d#e#
長度從5變成了11,也就是 2*n+1
如果是ab
#a#b#
長度從2變成了5,同樣是2*n +1
也就是說,不管是奇數個還是偶數個字母,變換完成以後,都是奇數個
然後進行分析,如果當前判斷的所在的下標被前面的迴文串的最右側下標所包含,,根據迴文串的對稱性,當前下標相對於前面的id有一個對稱點,這個點的迴文串長度我們已經算出來了,跟當前點到maxid的差值作比較,取小的,然後在這個基礎上繼續判斷迴文串的長度,也就是利用了前面應計算的結果,降低了計算量
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
char *longestPalindrome(char *s) {
int i=0,id,maxid,ans=1,pos=0;
//找到的最長迴文串的左端下標
int left;
//最長迴文串的臨時數組
char * result;
//字符串長度
int str_length=0;
while(s[i++]) str_length++;
//初始化新的數組,存放每個元素對應的迴文半徑
int p[2*str_length+3];
//構造新的字符數組,用來計算
char new_str[2*str_length+3];
new_str[0]='$';
new_str[1]='#';
for (i =0;i< str_length;i++){
new_str[2*i+2]=s[i];
new_str[2*i+3]='#';
}
new_str[2*str_length+2]='\0';
int len = 2*str_length+2;
// 對每個字符求其迴文半徑,利用前面的數組
// 最後面的'\0'不用求
// 第一個字符"$",p[0]=1
id = 0;
maxid = 1;
p[0] = 1;
for (i=1;i<len;i++){
// 判斷前一次的迴文最右端是不是包含當前判斷的字符
if (maxid > i){
p[i] = p[2*id-i] > (maxid-i)?(maxid-i):p[2*id-i];
}else{
p[i] = 1;
}
while(new_str[i+p[i]] == new_str[i-p[i]]){
p[i]++;
}
if(p[i]+i> maxid){
maxid = p[i]+i;
id = i;
}
if (ans<p[i]){
ans = p[i];
pos = i;
}
}
left = (pos-ans)/2;
result = (char*)malloc(sizeof(char)*ans);
for (i=0;i<ans-1;i++){
result[i] = s[left+i];
}
result[ans-1] = '\0';
return result;
}
int main() {
char * aa= "abb";
printf("%s\n", longestPalindrome(aa));
}
輸出:
/Users/zhangguohao/CLionProjects/untitled/cmake-build-debug/untitled
bb
Process finished with exit code 0