看WerKeyTom_FTD的题解把
先求出不跨两个串的,对于跨两个串的,枚举中心,然后易知一定在中心所在串向两边延伸尽量长之后再进另一个串
进另一个串之后二分+hash即可
马拉车都能写错……
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
int n,N;
char a[MAXN],b[MAXN];
int fa[MAXN],fb[MAXN];
int ans;
ll bas[2]={131,233};
ll mod[2]={1000000007,998244353};
ll h[MAXN][2],g[MAXN][2];
ll mi[MAXN][2];
bool OK(int len,int x,int y){
int i;
bool re=1;
for(i=0;i<2;i++){
ll X=(h[x][i]-h[x-len][i]+mod[i])%mod[i];
ll Y=(g[y][i]-g[y+len][i]+mod[i])%mod[i];
int c=x-(N-y+1);
if(c>=0){
re&=X==(Y*mi[c][i])%mod[i];
}else{
re&=(X*mi[-c][i])%mod[i]==Y;
}
}
return re;
}
int cal(int x,int y){
int l=1,r=min(x,N-y+1);
int re=0;
while(l<=r){
int mid=l+r>>1;
if(OK(mid,x,y)){
re=mid;
l=mid+1;
}else{
r=mid-1;
}
}
return re;
}
int main(){
int i,j;
scanf("%d%s%s",&n,a+1,b+1);
N=n;
for(j=0;j<2;j++){
mi[0][j]=1;
for(i=1;i<=n;i++){
mi[i][j]=mi[i-1][j]*bas[j]%mod[j];
}
for(i=1;i<=n;i++){
h[i][j]=(h[i-1][j]+a[i]*mi[i][j])%mod[j];
}
for(i=n;i;i--){
g[i][j]=(g[i+1][j]+b[i]*mi[n-i+1][j])%mod[j];
}
}
for(i=n;i;i--){
a[i<<1]=a[i];
a[i<<1|1]='*';
b[i<<1]=b[i];
b[i<<1|1]='*';
}
a[0]=b[0]='$';
a[1]=b[1]='*';
(n<<=1)|=1;
int mxa=1,nowa=1;
int mxb=1,nowb=1;
for(i=1;i<=n;i++){
fa[i]=min(fa[nowa*2-i],mxa-i);
fb[i]=min(fb[nowb*2-i],mxb-i);
for(;a[i+fa[i]+1]==a[i-fa[i]-1];fa[i]++){
}
for(;b[i+fb[i]+1]==b[i-fb[i]-1];fb[i]++){
}
if(i+fa[i]>mxa){
mxa=i+fa[i];
nowa=i;
}
if(i+fb[i]>mxb){
mxb=i+fb[i];
nowb=i;
}
}
for(i=1;i<=n;i++){
ans=max(ans,max(fa[i],fb[i]));
}
int l,r;
for(i=1;i<=n;i++){
if(fa[i]){
l=i-fa[i]+1>>1;
r=i+fa[i]-1>>1;
ans=max(ans,fa[i]+cal(l-1,r)*2);
}
if(fb[i]){
l=i-fb[i]+1>>1;
r=i+fb[i]-1>>1;
ans=max(ans,fb[i]+cal(l,r+1)*2);
}
}
printf("%d\n",ans);
return 0;
}
/*
7
abacadd
qwewbah
*/