最长回文串 马拉车算法

有两个长度均为n的字符串A和B。可以从A中选一个可以为空的子串A[l1…r1],B中选一个可以为空的子串B[l2…r2],满足r1=l2,然后把它们拼起来(A[l1…r1]+B[l2…r2])。求用这样的方法能得到的最长回文串的长度。注意:求的不是本质不同的回文串个数哦!!!

解题报告:找两个之间的最长回文串,只不过我卡了一下午而已,其实很简单,跑两遍马拉车,把两个字符串的len处理出来,开始枚举a的字符串的最后一个点,注意这里b的i-2是和a[i]是配对的,因为他们之间加了我们之前加过的字符,用tmp存他们的最大值,为什么呢?是为了减少匹配的次数,当他是最大值的时候不匹配也没事,因为可以是空串呀

#include
using namespace std;
const	int N=100010;
char a[N],b[N],str[N*2],str2[N*2];
int len1[N*2],len2[N*2];
void get_str1(char a[])
{
	int k=0;
	str[k++]='@';
	for(int i=0;a[i];i++)
	{
		str[k++]='#';
		str[k++]=a[i]; 
	}
	str[k++]='#';
	str[k]=0;
}
void get_str2(char a[])
{
	int k=0;
	str2[k++]='@';
	for(int i=0;a[i];i++)
	{
		str2[k++]='#';
		str2[k++]=a[i]; 
	}
	str2[k++]='#';
	str2[k]=0;
}
void mlc(char a[])
{
	int id=0,mx=0;
	for(int i=1;a[i];i++)
	{
		len1[i]=mx>i?min(mx-i,len1[2*id-i]):1;
		while(a[i-len1[i]]==a[i+len1[i]])	len1[i]++;
		if(i+len1[i]>mx)
		{
			mx=i+len1[i];
			id=i;
		}
	}
}
void mlc2(char a[])
{
	int id=0,mx=0;
	for(int i=1;a[i];i++)
	{
		len2[i]=mx>i?min(mx-i,len2[2*id-i]):1;
		while(a[i-len2[i]]==a[i+len2[i]])	len2[i]++;
		if(i+len2[i]>mx)
		{
			mx=i+len2[i];
			id=i;
		}
	}
}
int main()
{
	int n;
	cin>>n;
	scanf("%s",a);
	scanf("%s",b);
	get_str1(a);
	get_str2(b);
	mlc(str);
	mlc2(str2);
	int ans=0;
	for(int i=2;str[i];i++)
	{
		int tmp=max(len1[i],len2[i-2]);
		while(str[i-tmp]==str2[i-2+tmp])	tmp++;
		ans=max(ans,tmp-1);
	}
	cout<<ans<<endl;
}

你可能感兴趣的:(马拉车)