马拉车算法模板

本文最后更新于:3 years ago

模板来源:HKer_YM的博客
1.求最长回文长度或回文子串个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//求回文串的个数
inline int Manacher(string s)
{
//转换字符串
memset(hw, 0, sizeof(hw));
int len = s.length();
string nowString = "$#";
for(int i = 0; i < len; i++){
nowString += s[i];
nowString += "#";
}
//防止越界访问
nowString += "^";
len = nowString.length();
int maxRight = 0, mid = 0, maxAns = 0, numAns = 0;
//maxRight 最右边的位置 mid 中心的位置 maxAns 最长回文串的半径
for(int i = 1; i < len; i++){
if(maxRight > i){
//当中心点没超过最右边maxRight
hw[i] = min(maxRight - i, hw[(mid<<1) - i]);
}
else{
//否则,就重新往外扩
hw[i] = 1;
}
//如果当前不是最长, 就往外扩
while(nowString[i + hw[i]] == nowString[i - hw[i]]){
++hw[i];
}
//更新最右边的位置, 同时更新最长字串的半径
if(i + hw[i] > maxRight){
maxRight = i + hw[i];
mid = i;
}
//求最长回文串的长度
//maxAns = max(hw[i], maxAns);
//求回文串的个数
numAns += (hw[i] / 2);
}
//最长字串的长度等于半径减1
//return (maxAns - 1);
//回文串的个数
return numAns;
}

2.求最长的回文子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//求最长回文串
inline string Manacher(string s)
{
//转换字符串
memset(hw, 0, sizeof(hw));
int len = s.length();
string nowString = "$#";
for(int i = 0; i < len; i++){
nowString += s[i];
nowString += "#";
}
//防止越界访问
nowString += "^";
len = nowString.length();
int maxRight = 0, mid = 0, maxLen = 0, maxPoint = 0;
//maxRight 最右边的位置 mid 中心的位置 maxAns 最长回文串的半径
for(int i = 1; i < len; i++){
if(maxRight > i){
//当中心点没超过最右边maxRight
hw[i] = min(maxRight - i, hw[(mid<<1) - i]);
}
else{
//否则,就重新往外扩
hw[i] = 1;
}
//如果当前不是最长, 就往外扩
while(nowString[i + hw[i]] == nowString[i - hw[i]]){
++hw[i];
}
//更新最右边的位置, 同时更新最长字串的半径
if(i + hw[i] > maxRight){
maxRight = i + hw[i];
mid = i;
}
if(hw[i] > maxLen){
maxLen = hw[i];
maxPoint = i; //最长回文串的中心位置
}
}
//截取最长回文串
//这里为啥这样写,在本博客前文已经提到过: 1. 第一步,重组字符串
return s.substr((maxPoint - maxLen) / 2, maxLen - 1);
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!