這個也算是很經典的題目了,o(n)的解法還是要自己鑽進去想一想的,不能總以為自己會了,動手寫一寫才是王道。
題大家應該都知道,我就直接用ppt裡面的了。
例如ababcdedcbaab, 最長回文子串是abcdedcba。
暴力解法1:
列舉起點o(n)
列舉終點o(n)
判斷回文o(n)
總複雜度o(n^3)
暴力解法2:
列舉中間點o(n) (可能是兩個字元之間,可能是1個字元)
不斷延伸判斷回文o(n)
總複雜度o(n^2)
o(n)演算法: manacher
奇數偶數統一處理,每個字元前後乙個字串中沒出現的字元
例如aba,變為了#a#b#a#,這樣做的好處奇數、偶數統一處理。
定義陣列p[i],表示以i為中心[i – x ... i + x]是最長且回文的。
還是上例:
#a#b#a#
0103010
p[i]其實表示了原串中以該字元為中心的最長回文子串的長度(#表示原串中兩個字元之間的位置為中心)。
我們能否o(n)時間求出p陣列?
manacher演算法
算p[i]時假設p[0 ... i – 1]已經計算好了,對前面的p[x],我們定義乙個框[x – p[x] ... x + p[x]],定義right是max, center = argmax,即right是之前所有框的最右邊的位置,center是這個框的中心,框裡的串是個回文子串。
現在要計算p[i],我們算一下其關於center的對稱點i』 = center * 2 – i,問題關鍵是回文串的對稱性,從框左邊left...i』和i...right是一致的,如果p[i』]的長度能把i + p[i』]限制在框裡,則有p[i] = p[i』],因為框住的東西比較過了。
如果框不住p[i』]的長度,導致其超出i + p[i』]右邊界,就是框不住的東西,是需要比較的。
p[i]至少等於min。
繼續暴力比較,更新right。
為啥演算法是o(n)的?因為right只能增加n次……
code:
1擴充套件(codility gammar 2011)int maxhuiwen(string
str)211
int len =strcharp.length();
12int *p = new
int[len];
13 p[0] = 0;14
int l = 0, c = 0, r = 0, maxl = 1;15
for(int i = 1; i < len; ++i)
1627 maxl = maxl > p[i] ?maxl : p[i];28}
29delete p;
30return
maxl;
31 }
給定乙個全部由字母組成的字串,求這樣的下標對數(x,y)滿足x < y並且[x...y]的字串是回文的。如果數量超過10^8,返回-1。
p陣列告訴我們什麼?
如果p[i] = 6表示,我們實際上有乙個以i為中心長度為6的回文串,那麼長度為4和2依然是回文的,實際上包含了3個回文串。
如果p[i] = 5,實際上我們有3個長度分別為5,3,1的回文串。
我們不要長度為1的,也就是說我們求的是所有p[i]/2的和。
面試題 最長回文子串
在網上找了幾個版本,改編的,好難啊。加油。最大回文子串問題 include includeusing namespace std 返回最長的回文子串 char max substring bxy char str,int length for int i 0 i m i 不預先判斷奇偶,先奇後偶,m...
最長回文子串 最長回文子串行
1.最長回文子串行 可以不連續 include include include include using namespace std 遞迴方法,求解最長回文子串行 intlps char str,int i,int j intmain include include include using n...
筆試面試題(8) 回文子串
1 驗證整個字串是不是回文 最簡單的了 直接驗證或遞迴驗證都可以.2 求連續的回文子串,如 abdadbx,則回文子串就是bdadb 整個有乙個最優的演算法為 中心法求最長回文子串 線性複雜度 具體的部落格 寫的真好!include includeconst int m 110010 2 char ...