码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-04-28 09:49:22      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:第一个   zju   online   acm   poc   class   相等   ble   fine   

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)

标签:第一个   zju   online   acm   poc   class   相等   ble   fine   

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10781700.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!