【面試題】最長迴文子串

這個也算是很經典的題目了,O(n)的解法仍是要本身鑽進去想想的,不能總覺得本身會了,動手寫一寫纔是王道。面試

今天看了2013年9月15日北理工面試&算法講座by_July&曹鵬的PPT,真是後悔當時沒去聽啊,已經不記得當時幹什麼去了,反正應該沒有去聽講座有意義。。正題,而後又看到這個題,第N次看到了,卻還沒寫過,實在不該該,今天就寫了一下。話說,推薦 結構之法 算法之道 博客,博客置頂的博文裏面能夠找到PPT下載地址。算法

題你們應該都知道,我就直接用PPT裏面的了。數組

例如ababcdedcbaab, 最長迴文子串是abcdedcba。
暴力解法1:
枚舉起點O(n)
枚舉終點O(n)
判斷迴文O(n)
總複雜度O(n^3)
暴力解法2:
枚舉中間點O(n) (多是兩個字符之間,多是1個字符)
不斷延伸判斷迴文O(n)
總複雜度O(n^2)ui

O(n)算法: Manacher
奇數偶數統一處理,每一個字符先後一個字符串中沒出現的字符
例如aba,變爲了#a#b#a#,這樣作的好處奇數、偶數統一處理。
定義數組p[i],表示以i爲中心[i – x ... i + x]是最長且迴文的。
仍是上例:
#a#b#a#
0103010
P[i]其實表示了原串中以該字符爲中心的最長迴文子串的長度(#表示原串中兩個字符之間的位置爲中心)。
咱們可否O(n)時間求出p數組?spa

Manacher算法
算p[i]時假設p[0 ... i – 1]已經計算好了,對前面的p[x],咱們定義一個框[x – p[x] ... x + p[x]],定義right是max{x + p[x]}, center = argmax{x + p[x]},即right是以前全部框的最右邊的位置,center是這個框的中心,框裏的串是個迴文子串。
如今要計算p[i],咱們算一下其關於center的對稱點i’ = center * 2 – i,問題關鍵是迴文串的對稱性,從框左邊left...i’和i...right是一致的,若是p[i’]的長度能把i + p[i’]限制在框裏,則有p[i] = p[i’],由於框住的東西比較過了。.net

若是框不住p[i’]的長度,致使其超出i + p[i’]右邊界,就是框不住的東西,是須要比較的。code

p[i]至少等於min{p[i’], right – i}。
繼續暴力比較,更新right。
爲啥算法是O(n)的?由於right只能增長n次……blog

code:字符串

 1 int MaxHuiwen(string str)
 2 {
 3     if(str.empty())
 4         return 0;
 5     string strCharp = "#";
 6     for(int i = 0; i < str.length(); ++i)
 7     {
 8         strCharp += str[i];
 9         strCharp += "#";
10     }
11     int len = strCharp.length();
12     int *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)
16     {
17         int j = (c << 1) - i;
18         if(j >= 0 && i + p[j] < r)
19             p[i] = p[j] < r - i ? p[j] : r - i;
20         else
21         {
22             for(p[i] = 0; i-p[i]-1 >= 0 && i+p[i]+1 < len && strCharp[i+p[i]+1] == strCharp[i-p[i]-1]; ++p[i]);
23             c = i;
24             r = i+p[i];
25             l = i-p[i];
26         }
27         maxl = maxl > p[i] ? maxl : p[i];
28     }
29     delete p;
30     return maxl;
31 }

擴展(codility Gammar 2011)
給定一個所有由字母組成的字符串,求這樣的下標對數(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的和。get

相關文章
相關標籤/搜索