马拉

马拉车 Manacher

。_饼干妹妹 提交于 2020-02-09 01:31:13
Manacher,人称马拉车。是用来查找一个字符串的最长回文子串的线性算法。 对于一个子串长度有可能是偶数也可能是奇数。为了实现简单与准确,对原串更改。如 ababca 为 $#a#b#a#b#c#a# ,令新串为 s s s 。 定义 p i p_i p i ​ 为以 i i i 为对称中心的最长回文半径。刚刚栗子的 p p p 为 $ # a # b # a # b # c # a # 1 1 2 1 4 1 4 1 2 1 2 1 2 1 可以发现:非字母字符对应的 p i p_i p i ​ 为奇数,字母字符对应的 p i p_i p i ​ 为偶数。在新串中,因为有其它的字符,所以以 i i i 为中心的最长回文子串长度为 p i − 1 p_{i} - 1 p i ​ − 1 。那么初始化是简单明了的。 void init ( ) { str [ 1 ] = '$' ; str [ 2 ] = '#' ; for ( int i = 1 ; i <= n ; i ++ ) str [ i * 2 + 1 ] = s [ i ] , str [ i * 2 + 2 ] = '#' ; n = ( n + 1 ) * 2 + 1 ; } 难点在构造 p p p ,从左到右构造 p p p 数组。令 m x mx m x 为以 i d id i d

马拉车――最长回文子串长度、回文串个数

匿名 (未验证) 提交于 2019-12-03 00:03:02
题目链接 模板 1 #include < bits / stdc ++. h > 2 using namespace std ; 3 const int maxn = 3e5 + 5 ; 4 5 char s [ maxn ], str [ maxn ]; 6 int l1 , l2 , p [ maxn ], ans ; 7 8 void init () 9 { 10 str [ 0 ]= '$' ; 11 str [ 1 ]= '#' ; 12 for ( int i = 0 ; i < l1 ; i ++) 13 { 14 str [ i * 2 + 2 ]= s [ i ]; 15 str [ i * 2 + 3 ]= '#' ; 16 } 17 l2 = l1 * 2 + 2 ; 18 str [ l2 ]= '*' ; 19 } 20 int manacher () 21 { 22 int id = 0 , mx = 0 , ans = 0 ; 23 for ( int i = 1 ; i < l2 ; i ++) 24 { 25 if ( mx > i ) p [ i ]= min ( p [ 2 * id - i ], mx - i ); 26 else p [ i ]= 1 ; 27 for (; str [ i + p [ i ]]== str [ i - p