PHP實現 Manacher 最大回文子串演算法

2021-07-10 23:30:25 字數 2745 閱讀 4039

題目:給乙個字串,找出它的最長的回文子串行的長度。

例如,如果給定的序列是「bbabcbcab」,則輸出應該是7,「babcbab」是在它的最長回文子串行。

輸入:

aaaa

1212asdfdsa1144121

輸出:

47

這裡我們還是將其封裝成函式呼叫

回文序列就是正向和反向完全一樣的序列,比如asdfdsaaaaa

接下來我們由淺及深,一步一步來說一下manacher演算法,這裡我們只說 php 的實現

通過 php 很容易實現,只需要判斷正向反向是否相同就行了

function

huiwen

($str)

else

}

接下來我們就來講解最大回文子串如何去求

求回文子串,毫無疑問需要每個字元遍歷一遍,分別求出來各個字元的回文長度,然後選出最長的那乙個

**如下:

function

palindrome

($str)

if ($j > $max) }}

var_dump(substr($str, $pos - $max, $max * 2 + 1));

}

可以看到,這個**是有bug的,因為回文子串可能是奇數長度,也可能是偶數長度,因為我們是以乙個字元為中心來求的,所以用這種方法只能求出奇數長度的回文子串,接下來我們來改進一下

因為我們只能求出奇數長度的回文子串,因此我們需要把字串改進一下

首先通過在每個字元的兩邊都插入乙個特殊的符號,將所有可能的奇數或偶數長度的回文子串都轉換成了奇數長度。比如 abba 變成 #a#b#b#a#, aba變成 #a#b#a#,這樣我們再來看一下**:

function

palindrome

($str)

if ($j > $max) }}

$r = substr($newstr, $pos - $max, $max * 2);

$res = str_replace("#", "", $r);

var_dump($res);

}

這個樣子我們就寫好了基本的回文子串演算法了,但是在這個演算法中,我們用了兩層for迴圈,並且需要判斷當前字元的位置是否越界,效率較低,接下來我們來看manacher演算法

首先,為了進一步減少編碼的複雜度,可以在字串的開始和結尾加入另乙個特殊字元,這樣就不用特殊處理越界問題,這裡我們在開頭和結尾分別加入@\0,如abba變成@#a#b#b#a#\0

接下來,我們引入乙個輔助序列$p來記錄各個位置的回文長度(注意:我們這裡記錄的回文長度是單向的長度,比如12321我們記錄的回文長度為 3,實際回文長度是$p[$i] * 2 - 1

比如字串$s與輔助序列$p的對應關係如下:

最後,核心**在於這一句:

$p[$i] = $mx > $i ? min($p[$j], $mx - $i) : 1;

通過這步操作我們可以避免很多不必要的匹配,我們結合下面的**來理解這句操作

$mx是最大回文序列最右側邊界的座標,$i是當前要計算的位置,$j$i相對於最大回文序列中間座標$pos的對稱點

由於回文序列的性質,回文序列是對稱的,也就是說

如果:

$mx > $i

那麼$p[$i] >= $mx > $i ? min($p[$j], $mx - $i) : 1;

可以這麼理解:

如果$mx > $i,這時當前位置當前最大回文序列的右半部分裡面,根據回文序列的對稱性,可以得出,當前位置$i的回文長度一定大於等於與之對稱$j的回文長度,所以說直接從$j的回文長度開始計算

但是如果$mx > $i,這時當前位置當前最大回文序列之外,無法判斷$mx以後字元的對稱性,因此從 1 開始

function

palindrome

($str)

if ($p[$i] > $max)

}$r = substr($newstr, $pos - $max + 1, $max * 2 - 1);

$res = str_replace(array("#", "@", "\0"), "", $r);

var_dump($res);

}

manacher 演算法的時間複雜度為o(n),優勢在於避免了奇偶數討論的問題,簡化了邊界判斷,還記錄了當前字串的「回文狀態」,利用之前的回文狀態來求當前回文狀態 ,體現了動態規劃的思想

最大回文串 Manacher演算法

manacher演算法是針對於字串的乙個處理演算法,目的在於求解乙個字串的最大回文串。它的時間複雜度為o n 求解乙個字串的最大回文串最容易想到的就是從乙個字串出發將其作為中心,依次向兩端擴充套件,直到遇到不同的字元。這種演算法的最壞時間複雜度可以達到o n 2 除此之外對於偶數長度的最大回文串需要...

Manacher演算法C 實現

manacher演算法也稱 馬拉車演算法 是用來解決求字串的最長回文串的演算法。對於求最長回文串有三種演算法 1.暴力列舉法 優點 簡單易寫 缺點 複雜度過高 o n 3 string s cin s int maxlength 1,start 0 for int i 0 i s.size i if...

最大回文字串長度 manacher演算法

參考 題目 hdu3068 hdu3068.cpp 定義控制台應用程式的入口點。include stdafx.h include include include include using namespace std int longestpdr vector vc for int i 0 i rd...