L2-008 最长对称子串(马拉车 or 技巧暴力)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了L2-008 最长对称子串(马拉车 or 技巧暴力)相关的知识,希望对你有一定的参考价值。

题目链接

https://pintia.cn/problem-sets/994805046380707840/problems/994805067704549376

思路

法一

因为要求的是最长的对称子串,其实就是求最长回文子串,我们很容易就能和马拉车算法联系起来,由于这里数据比较水所以直接套板子就能过,如果没学过马拉车的话可以带一点技巧的暴力过去

法二

对于一个回文串,要么是奇数长度要么是偶数长度,那么我们只需要枚举中心位置以及回文半径即可,复杂度是 O ( N 2 ) O(N^2) O(N2)

法三

我们提前用字符串hash处理,然后同样是枚举回文中心以及回文半径

代码

马拉车

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

#define N 210005

char S[N],str[N*2+5];
int len1,len2,ans,p[N*2+5];

void init() //数组初始化,即数组长度翻倍 
	str[0] = '$';//为了防止数组越界 
	str[1] = '#';
	for(int i = 0; i < len1; ++i)
		str[i * 2 + 2] = S[i];
		str[i * 2 + 3] = '#';
	
	len2 = len1 * 2 + 2;
	str[len2] = '*';


void manacher() //manacher 
	init();
	int id = 0,mx = 0;//mx表示的是当前计算回文串最右边字符的最大值 
	for(int i=0; i < len2; ++i)
		p[i]=mx > i?min(p[id*2-i],mx-i) : 1;//p[i]=mx>i?min(p[id*2-i],m-i):1; 
		for(; str[i+p[i]] == str[i-p[i]]; p[i]++);//如果字符串对称则对称长度增加 
			if(p[i]+i > mx)//如果大于当前的最大长度则更新 
				mx=p[i]+i, id = i;
	


int main()

	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin.getline(S,N-1);
	len1 = strlen(S);
	manacher();
	int maxlen = 0;
	for(int i = 0; i < len2; ++i)
		maxlen = max(p[i], maxlen);
	cout<<maxlen-1<<endl;
	return 0;

暴力枚举

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int main()

	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	string s;
	getline(cin,s);
	int ans,tmp,len = s.size();
	ans = tmp = 0;
	
	for(int i = 0;i < len; ++i) 
		//长度为奇数情况
		tmp = 1;
		for(int j = 1; j < len; j++) 
			if(i - j < 0 || i + j >= len || s[i - j] != s[i + j])
				break;
			tmp += 2;
		
		ans = max(ans,tmp);
		//长度为偶数情况
		tmp = 0;
		for(int j = 1; j < len; j++) 
			if(i - j + 1 < 0 || i + j >= len || s[i - j + 1] != s[i + j])
				break;
			tmp += 2;
		
		ans = max(ans,tmp);
	
	cout<<ans<<endl;
	
	return 0;

以上是关于L2-008 最长对称子串(马拉车 or 技巧暴力)的主要内容,如果未能解决你的问题,请参考以下文章

L2-008 最长对称子串 (25分)

L2-008. 最长对称子串

马拉车算法

L2-008. 最长对称子串

L2-008. 最长对称子串

L2-008 最长对称子串 (25 分) (模拟)