题目描述
JYY有两个长度均为
的字符串
和
。
一个扭动字符串
由
中的第
个字符到第
个字符组成的子串与
中的第
个字符到第
个字符组成的子串拼接而成。
比如,若
,
,则扭动字符串
。
JYY 定义一个扭动的回文串为如下情况中的一个:
中的一个回文串;
中的一个回文串;
或者某一个回文的扭动字符串
现在 JYY 希望找出最长的扭动回文串。
输入输出格式
输入格式:
第一行包含一个正整数
。第二行包含一个长度为
的由大写字母组成的字符串
。第三行包含一个长度为
的由大写字母组成的字符串
。
输出格式:
输出的第一行一个整数,表示最长的扭动回文串。
输入输出样例
输入样例#1:
5
ABCDE
BAECB
输出样例#1:
5
说明
样例解释 最佳方案中的扭动回文串如下所示(不在回文串中的字符用 . 表示):
对于所有的数据,
分析:
我们枚举答案回文串的中点
,假设在
串(
串同理)。维护两个指针,一个往左,一个往右,判断相不相等。如果不相等,再把右指针移动到B串。(就是能在A串中延伸就延伸,延伸不了在转B串)。
那么相当于A串中找一个以
为中心的最长回文串,manacher解决。然后继续匹配部分可以用hash+二分解决。
求最长回文串其实也可以用hash+二分解决。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const int maxn=2e5+7;
const LL mod[2]={998244353,1e9+9};
using namespace std;
int n,len,ans;
char a[maxn],b[maxn],stra[maxn],strb[maxn];
int pa[maxn],pb[maxn];
LL ha[maxn][2],hb[maxn][2],bit[maxn][2];
void change(char *s,char *str)
{
for (int i=1;i<=n;i++)
{
str[i*2-1]='#';
str[i*2]=s[i];
}
str[n*2+1]='#';
}
void manacher(char *str,int *p)
{
int pos=0;
for (int i=1;i<=len;i++)
{
if (i<=pos+p[pos]) p[i]=min(p[2*pos-i],pos+p[pos]-i);
while ((i+p[i]+1<=2*n+1) && (i-p[i]-1>=1) && (str[i+p[i]+1]==str[i-p[i]-1])) p[i]++;
if (i+p[i]>=pos+p[pos]) pos=i;
}
}
bool check(int la,int ra,int lb,int rb)
{
LL ga[2],gb[2];
for (int j=0;j<2;j++) ga[j]=(ha[ra][j]+mod[j]-ha[la-1][j]*bit[ra-la+1][j]%mod[j])%mod[j];
for (int j=0;j<2;j++) gb[j]=(hb[lb][j]+mod[j]-hb[rb+1][j]*bit[rb-lb+1][j]%mod[j])%mod[j];
return (ga[0]==gb[0]) && (ga[1]==gb[1]);
}
int solve(int x,int y)
{
int l=1,r=min(x,len-y+1),ans=0;
while (l<=r)
{
int mid=(l+r)/2;
if (check(x-mid+1,x,y,y+mid-1)) l=mid+1,ans=mid;
else r=mid-1;
}
return ans;
}
int main()
{
scanf("%d",&n);
scanf("%s",a+1);
scanf("%s",b+1);
change(a,stra);
change(b,strb);
len=2*n+1;
manacher(stra,pa);
manacher(strb,pb);
bit[0][0]=bit[0][1]=1;
for (int i=1;i<=len;i++)
{
int c;
if (stra[i]=='#') c=26;
else c=stra[i]-'A';
for (int j=0;j<2;j++) ha[i][j]=(ha[i-1][j]*27+c)%mod[j];
for (int j=0;j<2;j++) bit[i][j]=bit[i-1][j]*27%mod[j];
}
for (int i=len;i>0;i--)
{
int c;
if (strb[i]=='#') c=26;
else c=strb[i]-'A';
for (int j=0;j<2;j++) hb[i][j]=(hb[i+1][j]*27+c)%mod[j];
}
for (int i=1;i<=len;i++)
{
int l=i-pa[i]-1,r=i+pa[i]-1;
ans=max(ans,pa[i]+solve(l,r));
}
for (int i=1;i<=len;i++)
{
int l=i-pb[i]+1,r=i+pb[i]+1;
ans=max(ans,pb[i]+solve(l,r));
}
printf("%d",ans);
}