ZOJ4110 Strings in the Pocket(2019浙江省赛)
给出两个字符串,询问有多少种反转方法可以使字符串1变成字符串2。
如果两个串相同,就用马拉车算法找回文串的数量~
如果两个串不同,从前往后找第一个不同的位置l,从后往前找第二个不同的位置r,反转l和r,判断是否成功~
如果不成功,记为0
如果成功,以l和r为起点判断是否能反转,记录次数
#include<bits/stdc++.h> using namespace std; const int maxn=2e6+100; typedef long long ll; char s1[maxn]; char s2[maxn]; char s[maxn*2]; int len[maxn*2]; int init(char *str){ int n=strlen(str); for(int i=1,j=0;i<=2*n;j++,i+=2){ s[i]='#'; s[i+1]=str[j]; } s[0]='$'; s[2*n+1]='#'; s[2*n+2]='@'; s[2*n+3]='\n'; return 2*n+1; } void manacher(int n){ int mx=0,p=0; for(int i=1;i<=n;i++){ if(mx>i) len[i]=min(mx-i,len[2*p-i]); else len[i]=1; while(s[i-len[i]]==s[i+len[i]]) len[i]++; if(len[i]+i>mx) mx=len[i]+i,p=i; } } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%s",s1); scanf("%s",s2); int Len=strlen(s1),l=-1,r=Len; for(int i=0;i<Len;i++){ if(s1[i]!=s2[i]){ l=i;break; } } for(int i=Len-1;i>=0;i--){ if(s1[i]!=s2[i]){ r=i;break; } } if(l==-1){ ll ans=0; int n=init(s1); manacher(n); for (int i=1;i<=n;i++) ans+=len[i]/2; printf("%lld\n",ans); continue; } else{ int tmp=0; for(int i=l;i<=r;i++){ if(s1[i]!=s2[l+r-i]){ tmp=1; break; } } if(tmp==1){ printf("0\n"); continue; } else{ ll ans=1;l--;r++; while (l>=0&&r<Len&&s1[l]==s2[r]&&s1[r]==s2[l]){ l--;r++;ans++; } printf("%lld\n",ans); } } } return 0; }