【分类讨论】CodeForces - 1006D·Two Strings Swaps

题目

传送门

题目大意

给你两个字符串 a b ,长度均为 n ,你可以对两个字符串进行如下操作( 1 i n ):

  • 交换字符 a i a n i + 1
  • 交换字符 a i b i
  • 交换字符 b i b n i + 1

如果想要通过这些操作使两个字符串相等,大多数情况下不可能。所以你需要进行预处理:将 a 中的某些字符改变,使得能够通过这些操作使两个字符串相等。注意只能改变 a 中的字符。

分析

观察这3个操作,其实只是对4个位置进行交换:
图1
也就是说, a i a n i + 1 b i b n i + 1 这几个字符的位置可以随便换。
所以需要保证这4个位置 只有2种字符,每种字符有2个或者只有1种字符
枚举时统计四个位置的字符是那些,疯狂分类讨论即可(以下内容建议自己想):

  • 当有1种字符时:不用管
  • 当有2种字符时:
    • 如果是2+2,不用管
    • 如果是1+3,Ans++
  • 当有3种字符时:
    • 如果 a i = a n i + 1 ,说明 b i b n i + 1 a i ,在预处理时你又不能改变 b ,所以只能把 a i a n i + 1 分别改成 b i b n i + 1 ,故Ans+=2
    • 如果 b i = b n i + 1 ,说明 a i a n i + 1 b i ,只需要把 a i 改成 a n i + 1 即可,故Ans++
  • 当有4种字符时:Ans+=2

还有一点:当 n 是奇数时,注意判断 a n + 1 2 b n + 1 2 是否一样。

代码

#include<cstdio>
#include<cstring>

#define MAXN 100000
int N,cnt[30];
char str1[MAXN+5],str2[MAXN+5];

int main(){
    scanf("%d",&N);
    scanf("%s%s",str1+1,str2+1);
    int Ans=0;
    if(N&1) Ans+=str1[N/2+1]!=str2[N/2+1];//中间两个字符
    for(int i=1;i<=N/2;i++){
        memset(cnt,0,sizeof cnt);
        cnt[str1[i]-'a']++;cnt[str1[N-i+1]-'a']++;
        cnt[str2[i]-'a']++;cnt[str2[N-i+1]-'a']++;
        int kind=0,flag=0;
        for(int j=0;j<26;j++)
            if(cnt[j]){
                kind++;//统计字符种类
                if(cnt[j]&1)
                    flag=1;//为了判断kind=2时1+3的情况
            }
        if(kind==2&&flag)
            Ans++;
        else if(kind==3)
            Ans+=(str1[i]==str1[N-i+1])+1;//看字符串1中的两个字符是否相等即可
        else if(kind==4)
            Ans+=2;
    }
    printf("%d",Ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/c20190102/article/details/81128440
今日推荐