HDU 3068 - 马拉车(manacher)算法模板题

马拉车(manacher)算法可以在O(n)时间内求出最长回文子串或回文子串的个数。

马拉车一开始还是比较晦涩难懂的,这里推荐两篇文章,可以帮助了解马拉车算法的思想:

漫画:如何找到字符串中的最长回文子串?

一文让你彻底明白马拉车算法

第一篇使用了漫画讲解,相对第二篇文章更容易理解马拉车算法的思想,但代码实现上不如第二篇简洁。故推荐先阅读第一篇,要实现代码时再参照第二篇。

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 3e5 + 5;
char s[maxn], t[maxn];
int p[maxn];

int main(){
	while(~scanf("%s", s)){
		int l = strlen(s), len = 0;
		t[len++] = '$';  // 在字符串开头和结尾都添加一个特殊字符(如'$', 注意不要相同),使后续计算可以避免判断越界 
		t[len++] = '#';
		for(int i = 0; i < l; ++i){
			t[len++] = s[i];
			t[len++] = '#';
		}
		t[len] = '&'; 
		
		int center = 0, max_right = 0;
		for(int i = 1; i < len; ++i){
			int i_mirror = 2 * center  - i;
			if(max_right > i){  // 在最右边界的覆盖范围内, 就利用回文串特征计算长度 
				p[i] = min(max_right - i, p[i_mirror]);  // 使用min()是为了防止超出最右边界 
			}
			else {
				p[i] = 0;
			}
			while(t[i - 1 - p[i]] == t[i + 1 + p[i]])
				++p[i];
			
			if(i + p[i] > max_right){  // 更新右边界的回文串中心
				center = i;
				max_right = i + p[i];
			}
		}
		
		int max_len = 0;  
		// int pos = 0;  //记录最长回文子串中心的位置 
		for(int i = 1; i < len; ++i)
			if(max_len < p[i]){
				max_len = p[i];
				// pos = i;
			}
		printf("%d\n", max_len);  //最长回文串的起始位置为: (pos - max_len) / 2
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值