牛客题霸 [ 最长回文子串] C++题解/答案
牛客題霸 [ 最長回文子串] C++題解/答案
題目描述
對于一個字符串,請設計一個高效算法,計算其中最長回文子串的長度。
給定字符串A以及它的長度n,請返回最長回文子串的長度。
題解:
兩個方法:
一個是經典暴力,這個大家應該都會
還一個是manacher(馬拉車)
馬拉車是專門處理回文串的算法
介紹兩個變量
id:回文子串的中心位置
mx:回文子串的最后位置
p[i]:以i為中心的回文半徑長度
當前,我們已經得到了 p[0…i-1],想要計算出 p[i] 來。
紅1為以 j 為中心的回文子串,紅2為以 i 為中心的回文子串,紅3為以 id 為中心的回文子串(首尾兩端分別為mx的對稱點和mx)。
那么,如果 mx 在 i 的右邊,則我們可以通過已經計算出的 p[j] 來計算 p[i],其中 j 與 i 的中心點為 id。這里分兩種情況:
先直接令 p[i] 的回文子串就等于 p[j] 的回文子串,即紅2長度等于紅1,然后判斷紅2的末尾是否超過了 mx,如果沒有超過,則說明 p[i] 就等于 p[j]。
為什么呢?
因為以 id 為中心的回文子串為紅3,包含了紅1和紅2,而且紅1和紅2以 id 為中心,那么一定有紅2=紅1。并且已經知道,紅1是以 j 為中心的最長子串,那么紅2也肯定是以 i 為中心的最長子串。
如果紅2的末尾超過了 mx,那么就只s能讓 p[i] = mx - i了,即我可以保證至少半徑到 mx 這個位置,是可以回文的,但是一旦往右超出了 mx,就不能保證了,剩下的只能用笨方法慢慢擴張來得到最長回文子串。
那如果紅2的左邊超出了mx的對稱點,怎么辦?不會出現這種情況的,因為紅1的右邊不會超過mx。如果超過了mx,那么在上一次迭代中,id應該更新為j,mx應該更新為 j+p[j]。在迭代中,會始終保證 mx 是所有已經得到的回文子串末端最靠右的位置。
另外,如果 mx 不在 i 的右邊呢?那就利用不了紅3的對稱性了,只能使用笨方法慢慢擴張了。
代碼:
class Palindrome { public:int p[100010], id = 0, mx = -1, maxx = -1;int getLongestPalindrome(string A, int n) {// write code herestring str = "@#";for ( int i = 0; i < n; i++ ) {str += A[i];str += '#';}for ( int i = 0; i < str.size(); i++ ) {if ( i < mx ) p[i] = min(p[ id * 2 - i], mx - i);else p[i] = 1;while ( str[i-p[i]] == str[i + p[i]]) p[i]++;if ( p[i] + i > mx) {id = i;mx = p[i] + i;}maxx = max(maxx, p[i]-1);}return maxx;} };總結
以上是生活随笔為你收集整理的牛客题霸 [ 最长回文子串] C++题解/答案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 庐组词语 庐组词语精选
- 下一篇: 牛客题霸 [找到字符串的最长无重复字符子