2019浙江省赛K zoj4110 Strings in the Pocket(manachar)

Posted virtu0s0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019浙江省赛K zoj4110 Strings in the Pocket(manachar)相关的知识,希望对你有一定的参考价值。

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6012

题意

给你两个串,可以翻转a串的一个区间,问有多少对l,r使得翻转后的a串等于b串

题解

  • 沙比提,比赛时想了想两个串相等就用马拉车求回文子串个数,觉得两个串不相等情况很复杂就没想下去了,其实两个串不相等的情况更好处理
  • 两个串不一样的话,一定需要翻转第一个和最后一个不相等的位置(关键),判一下中间是不是回文串,然后维护一下两边即可
  • 特判只有一个字符不相等的时候

代码

#include<bits/stdc++.h>
#define MAXN 2000005
#define ll long long 
using namespace std;
char a[MAXN],b[MAXN];
int n,odd[MAXN],eve[MAXN],T;
ll manachar(){
    int l=0,r=0,x;
    ll ans=0;
    for(int i=1;i<=n;i++){
        if(i>r)x=1;
        else x=min(odd[l+r-i],r-i);
        while(i-x>=1&&i+x<=n&&a[i-x]==a[i+x])x++;
        odd[i]=x;
        ans+=x;
        if(i+x-1>r){r=i+x-1;l=i-x+1;}
    }
    l=r=0;
    for(int i=1;i<=n;i++){
        if(i>r)x=0;
        else x=min(eve[l+r-i+1],r-i+1);
        while(i-x-1>=1&&i+x<=n&&a[i-x-1]==a[i+x])x++;
        eve[i]=x;
        ans+=x;
        if(i+x>=r){l=i-x;r=i+x-1;}
    }
    return ans;
}
int main(){
    cin>>T;
    while(T--){
        scanf("%s",a+1);scanf("%s",b+1);
        n=strlen(a+1);
        int L=1,R=n;
        for(;L<=n;L++)if(a[L]!=b[L])break;
        for(;R>=1;R--)if(a[R]!=b[R])break;
        if(L==R){printf("0\n");continue;}
        else if(L<=n){
            int ans=1;
            for(int i=L;i<=R;i++){
                if(a[i]!=b[L+R-i]){ans=0;break;}
            }
            if(ans){
                L--;R++;
                while(L>=1&&R<=n&&a[L]==b[R]&&a[R]==b[L]){ans++;L--;R++;}
            }
            printf("%d\n",ans);
        }else{
            printf("%lld\n",manachar());
        }
    }
}

以上是关于2019浙江省赛K zoj4110 Strings in the Pocket(manachar)的主要内容,如果未能解决你的问题,请参考以下文章

zoj4110 Strings in the Pocket(manacher)

浙江省赛真题2018

浙江省赛 ZOJ4029

2017浙江省赛 A - Cooking Competition ZOJ - 3958

2017浙江省赛 B - Problem Preparation ZOJ - 3959

2017浙江省赛 E - Seven Segment Display ZOJ - 3962