有两个长度均为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<iostream>
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;
}