题意:两个串s,t,多少对不同的(l,r),使得翻转s[l,r]后s等于t。
分析: s不等于t时,找出左右两端第一个不相等的位置a,b,首先判断翻转[a,b]后s是否等于t,接着往左右两端扫一遍判断字符是否相等。s等于t时,很容易想到就是s的回文串个数。。。。
一开始没看空间限制用回文自动机一直Segmentation Fault ,改为马拉车算法即可。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const int N=2e6+50;
char s1[N],s2[N],s[N*2];
int len[N*2];
int mi(int a,int b){
if(a<b) return a;
return b;
}
int main(){
int t,i,n,k,p,ma;
scanf("%d",&t);
while(t--){
scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1);
k=1;
for(i=1;i<=n;i++) if(s1[i]!=s2[i]) k=0;
if(k){
for(i=1;i<=n+1;i++){
s[i*2]=s1[i];
s[i*2-1]='*';
}
s[0]='#';
p=ma=0;
long long ans=0;
for(i=1;i<=2*n;i++){
if(ma>i) len[i]=mi(ma-i,len[2*p-i]);
else len[i]=1;
while(s[i+len[i]]==s[i-len[i]]) len[i]++;
if(ma<len[i]+i){
ma=len[i]+i;
p=i;
}
ans+=len[i]/2;
}
printf("%lld\n",ans);
}
else{
int l=1,r=n,ans=1;
while(s1[l]==s2[l]) l++;
while(s1[r]==s2[r]) r--;
for(i=l;i<=r;i++) if(s1[i]!=s2[r-(i-l)]) ans=0;
if(ans==0) printf("0\n");
else{
ma=1;
while(l-ma>=1&&r+ma<=n&&s1[l-ma]==s1[r+ma]) ma++;
printf("%d\n",ma);
}
}
}
return 0;
}