回文子串和回文子串行不同:
子串,一定要連續其實最長回文子串是可以轉換成lcs來做的,具體方法就是:子串行,不一定連續
將原串生成反向串,然後用dp求原串和反向串的lcs但是這樣缺點也很明顯的是o(n*n)的複雜度,即使優化到:滾動陣列+下標找反向串,也不能從根本上解決這個演算法的低效。
如果想在 o(n) 時間內解決回文子串問題呢?
答案就是manacher演算法,用一句話來概括這個演算法:
通過記錄已匹配的最右位置和對應的對稱中心來跳過一些沒用的比較在下面的**中,這個已匹配的最右位置就是mx,對稱中心就是id。
完整模板
int manacher(string tmp)
s[2*k] = '#';
s[2*k+1] = '\0';
//演算法核心
len=strlen(s);
int mx =0; //mx 記在i之前的回文串中,延伸至最右端的位置
int id=0; //id 記下取得這個最優mx時的 座標值
for (int i=0;i
}int res =0;
for (int i=0;i
return res-1;
}
演算法在字串開頭、結尾、字元之間都插入特殊字元(這裡用』#』),這樣就巧妙的把奇數的回文串和偶數的回文串統一起來考慮了(統一為奇數),不然處理回文串會很麻煩。
比如:abc 變成 #a#b#c# 這樣有7個字元。
abcd 變成 #a#b#c#d# 有9個字元。
可能有疑問:預處理成這樣,後面不是要算回文子串長度的時候,又要減去這些特殊字元嗎。
其實不會,因為演算法用 p[i] 來記錄 i 這個 pos 的最長單臂子串長度,比如 #a#b#c#b#a# 這個單臂子串長度為 #a#b#c,即長度為6,
而這裡有乙個很好的性質,p[i]-1 就是該回文子串在原串中的長度。即 abcba 就是5其實manacher演算法的核心**很簡單,但是理解起來感覺相當精妙,果然是演算法是**寫成的詩歌。
核心**:
//演算法核心
len=strlen(s);
int mx = 0; //mx 記在i之前的回文串中,延伸至最右端的位置
intid=0; //id 記下取得這個最優mx時的 座標值
for (int i=0;iif( i < mx ) //在當前最優邊界左邊
p[i] = min(p[2*id-i],mx-i); //算出對稱初始值
else
p[i]=1; //如果超出mx邊界,p[i]初始值為1
for (;s[i-p[i]] == s[i+p[i]] && s[i-p[i]] != '\0' && s[i+p[i]] != '\0' ; ) //對於超出mx或者p[j]邊界的計算
p[i]++;
if( p[i]+i > mx )
}
演算法開始是會通過乙個if else判斷來決定p[i]的初始值。
演算法的關鍵點就在這裡:
if( i < mx ) //在當前最優邊界左邊
p[i]= min(p[2*id-i],mx-i); //算出對稱初始值
else
p[i]=1; //如果超出mx邊界,p[i]初始值為1
那為什麼是 min(p[2*id-i],mx-i) 呢?
這種情況下,整個 中心i(或中心j) 的子串都涵蓋在 中心為 id,長度為 mx-id 的巨型臂膀下,由於 id為中心的完全對稱,必然 p[j] == p[i],
這種情況下,是 id 的臂展無法完全包裹 以i為中心的臂展時:
根據對稱性可知,圖中兩個綠框所包圍的部分是相同的,也就是說以 i 為中心的回文子串,其向右至少會擴張到mx的位置,也就是說 p[i] >= mx - i。至於mx之後的部分是否對稱,就只能乙個乙個匹配了。
另外特別要注意的是,要注意設定「哨兵」,也就是自己設定特殊字元或者』\0』代表邊界,不然後面的
for (;s[i-p[i]] == s[i+p[i]] ; p[i]++);
就會越界。
給出我畫出的原手稿
下圖中,當i為13時,臂展最大,但是這個字元的p[i]初始化為6,即 i = 5那個點 『c』。
[1]
[2]
最長回文子串模板
這裡先提前注意一下,子串和子串行是兩個不同的東西 回文串是面試常常遇到的問題 雖然問題本身沒啥意義 本文就告訴你回文串問題的核心思想是什麼。首先,明確一下什 回文串就是正著讀和反著讀都一樣的字串。比如說字串aba和abba都是回文串,因為它們對稱,反過來還是和本身一樣。反之,字串abac就不是回文串...
近似回文串 最長回文子串
輸入一行文字,輸出最長近似回文詞連續子串。所謂近似回文詞是指滿足以下條件的字串 1.s以字母開頭,字母結尾 2.a s 和b s 最多有2k個位置不同,其中a s 是s刪除所有非字母字元並且把所有字母轉化成小寫之後得到的串,b s 是a s 的逆序串。比如當k 1時,race cat是乙個近似回文詞...
回文子串對 擴充套件kmp kmp與回文子串
problem 1 回文子串對 manacher.cpp c pas 題目描述 給定一長度為n的小寫字母串,求有多少對回文子串,它們的交集非空。一對回文子串的交集非空 a,b c,d a c或b d 為2個回文子串,且 a,b c,d 輸入格式 第一行乙個整數n表示串長。第二行長度為n的小寫字母串。...