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; 
} 

 

posted @ 2020-02-14 15:32  zlc0405  阅读(158)  评论(0编辑  收藏  举报