题目链接:https://cn.vjudge.net/problem/ZOJ-4110
题意:对称的交换a串中的一个区间,使其和b一样,问多少种方案
题解:如果存在不一样的部分,那肯定就是最左边的不一样的位置 l 和最右边的不一样的位置 r ,交换这个区间,如果可以的话,判断一下还能不能扩大,如果不行,那就是0了,如果这两个串一样,那就看,a中有多少回文串,马拉车跑一遍即可
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+100;
int T;
char a[N],b[N];
char s[N*2];
int p[N*2];
int len,lena;
bool judge(){
int lena=strlen(a),lenb=strlen(b);
if(lena!=lenb){
printf("0\n");
return 0;
}
int i,j;
for(i=0;i<lena;++i)
if(a[i]!=b[i])break;
if(i==lena)return 1;
for(j=lena-1;j>=0;--j)
if(a[j]!=b[j])break;
int ti=i,tj=j;
while(i<=tj&&j>=ti&&a[i]==b[j]){
i++;
j--;
}
if(i<=tj && j>=ti)
printf("0\n");
else{
i=ti;
j=tj;
int ans=0;
for(int k=1;ti-k>=0&&tj+k<lena;++k){
if(a[ti-k]==a[tj+k])ans=k;
else break;
}
printf("%d\n",ans+1);
}
return 0;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%s",a);
scanf("%s",b);
if(judge()){
s[0]='0',s[1]='#';
len=strlen(a);
for(int i=0;i<len;i++)
{
s[i*2+2]=a[i];
s[i*2+3]='#';
}
s[len*2+2]='1';
long long ans=0;
int maxx=0,id;
for(int i=2;i<=len*2+1;i++)
{
p[i]=maxx>i?min(p[id-(i-id)],maxx-i):1;
while(s[i+p[i]]==s[i-p[i]]) p[i]++;
if(i+p[i]>maxx)
{
maxx=i+p[i];
id=i;
}
if(s[i]=='#')ans+=(p[i]-1)/2;
else ans+=p[i]/2;
}
printf("%lld\n",ans);
}
}
return 0;
}