最長回文子串四種方法

2021-08-28 16:07:40 字數 3968 閱讀 5024

這個應該是最容易的方法了,但是一看複雜度o(n3),還是放棄好了。

但是這個方法也是遍歷所有字串字串的一種方法。

下面是暴力搜尋的**:

// 暴力迴圈

public

static string maxpalindromestringforce

(final string target)}}

return target.

substring

(beginindex, beginindex + maxlen);}

public

static

boolean

ispalindromestring

(final string target)

l++; r--;}

return

true

;}

這個比暴力搜尋複雜度要少乙個數量級

為什麼呢?它用到了回文串的乙個特性左右對稱

其實在暴力搜尋的判斷是否為回文串的時候我們已經用了這個特性了

但是我們是對每一段字串用這個特性即用它去判斷而不是去獲取

所以我們對每乙個字元從中間向外展開以獲取以此字元為中心的最長回文字串

這樣外迴圈為字串遍歷 內迴圈為獲得回文子串 複雜度最差意思就是o(n2)

但是有乙個地方必須注意,中心拓展中心一詞是相對於長度為奇數的串的,

對於偶數串我們要單獨判斷,方法也很簡單看看該字元後乙個字元是不是一樣就行,**裡有解釋

**如下:

// 中心向外拓展

public

static string maxpalindromestringcenter

(final string target)

l++; r--;if

(r - l > end - beg)

// 回文串是偶數

if(i < target.

length()

-1&& target.

charat

(i +1)

== target.

charat

(i))

l++; r--;if

(r - l > end - beg)}}

return target.

substring

(beg, end +1)

;}

字串類的題目怎麼可能少了動態規劃呢

那麼狀態該怎麼轉移呢

d p[

i][j

]=

true,str[i]==str[j]&dp[i+1][j-1]==true \\ false \end

dp[i][

j]=}

for(

int i =

0; i < len; i++)}

for(

int strlen =

3; strlen <= len; strlen++)}

}return target.

substring

(beginindex, beginindex + maxlen)

;}很多人也許和我一樣聽到最長回文子串還有o(n)解法的時候是不相信的

但是事實就是如此,這個演算法也叫馬拉車演算法(只是諧音哦)

我認為它也是一種動態規劃思想 但是用的更加的巧妙

在某種程度上和kmp演算法有異曲同工之處

不知道是否有人注意到了上面幾種演算法在某些方面都考慮奇數串和偶數串的情況

為了簡化考慮情況設定一下規則:

a bc

d→#a

#b#c

#d

#abcd\rightarrow \#a\#b\#c\#d\#

abcd→#

a#b#

c#d#

這樣所有的字串就都是奇數串了

我們需要的是源字串啊

處理成那種亂七八糟的字串,即使得到了結果還要將所有#取代

所以我們看看能不能找到新串和原串之間的關係

這樣處理後表達乙個回文串最好的方式就是中心mid(也就是為什麼統一為奇數串的原因)和半徑來表示r

在我們知道mid和r的時候怎麼確定原串呢。

假設有串#c#a#b#a#原串是caba

顯而易見的是aba是回文串a在原串的下標是1

在新串中下標是5,也就是mid = 5 , r = 4

乍一看就是beginindex = mid-r

但是#a#b#a# 此時 mid = 3, r = 4那麼beginindex = -1

顯然不對所以我們在最開始處加上乙個與#不同的符號$,那麼新串即是 $#a#b#a#

此時mid = 4 r = 4那就很符合了

但是對#c#a#b#a#又不符合了,所以我們找到了新的關係beginindex = (mid-r)/2這是最符合的 感興趣的小夥伴可以自己推一推

p[i] = mostright > i ? min(p[2 * mid - i], mostright - i) : 1;

p[i] 為以i為中心的半徑 mostright是已知的回文串右端點最右的那個的下標 mid則是其中心

由於回文串的對稱性p[i] = min(p[2 * mid - i], mostright - i)p[2*mid-i]是其對稱中心點下標

他們兩個在以mid為中心的回文串內對稱部分相同也就是半徑相同(一定注意是回文串內)

在外面的部分我們無從得知只能老老實實匹配 也就是置為1(自己就是回文串)

因為每次迴圈內要不是用到以前的結論(對於的中心點)要麼就是向右拓展

所以複雜度是o(n)

並不是有兩個迴圈複雜度就是o(n2)

// manacher

public

static string maxpalindromestringmanacher

(final string target)

// 防止$#a#b#a# 讀到最後a的時候向兩邊擴散的時候溢位 c++則不需要c++字串有/0結束符最後加的字元不能為$否則還是會溢位

temp.

('&');

int[

] p =

newint

[temp.

length()

+1];

//以i為中心的半徑

int mostright =0;

// 已知回文串所能達到的最右邊的下標

int mid =0;

// 已知最右邊的回文串的中心下標

int reslen =1;

int resmid =0;

for(

int i =

1; i < temp.

length()

-1; i++)if

(reslen < p[i])}

return target.

substring

((resmid - reslen)/2

,(resmid - reslen)/2

+ reslen -1)

;}

如果還有疑惑 可以參考下面兩篇文章(我覺得很不錯的):

(我也是這裡學習的)

(漫畫的形式講的很清楚)

不好的地方 歡迎提出( ̄▽ ̄)"

最長回文子串 最長回文子串行

1.最長回文子串行 可以不連續 include include include include using namespace std 遞迴方法,求解最長回文子串行 intlps char str,int i,int j intmain include include include using n...

子執行緒更新UI的四種方法

mtvcontent findviewbyid r.id.tv content new thread start mtvcontent findviewbyid r.id.tv content new thread start private handler handler newhandler r...

最長回文子串

描述 輸入乙個字串,求出其中最長的回文子串。子串的含義是 在原串連續出現的字串片段。回文的含義是 正著看和倒著看是相同的,如abba和abbebba。在判斷是要求忽略所有的標點和空格,且忽略大小寫,但輸出時按原樣輸出 首尾不要輸出多餘的字串 輸入字串長度大於等於1小於等於5000,且單獨佔一行 如果...