Codeforces #324 Div2 C Marina and Vasya(构造)

题目链接:
Codeforces #324 Div2 C Marina and Vasya
题意:
给出两个长度为n个小写英文字母字符串s1和s2,构造一个长度为n的小写字母字符串使得这个字符串
和给出的每个字符串的不相同字母个数都是t个,如果不存在这样的构造输出-1。
分析;
题意也即是构造的字符串ans要有n-t个位置分别和s1,s2相同.
假设s1和s2相同位置相同字母的个数是cnt个,不妨令构造字符串ans这cnt个位置都是和s1,s2相同的
那么ans还需要有n-cnt-t个位置和s1相同,n-cnt-t个位置和s2相同,并且这两个n-cnt-t的位置必须是不同的位置。
因为相应位置上的s1字母和s2字母是不同的。那么就需要ans字符串至少有len=t+2*(n-cnt-t)=2*n-2*cnt-t的长度。
当len>n,即n>2*cnt+t时,就肯定构造不出符合题意的字符串了。然后允许构造的话,就按照上面的方式构造即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
using namespace std;
const int MAX_N=100010;

int n,t;
char s1[MAX_N],s2[MAX_N];
int ans[MAX_N];

int main()
{
    IOS;
    freopen("C.in","r",stdin);
    while(~scanf("%d%d",&n,&t)){
        scanf("%s%s",s1,s2);
        memset(ans,-1,sizeof(ans));  //ans[i]=0,对应字母'a'
        int cnt=0;
        for(int i=0;i<n;i++){
            if(s1[i]==s2[i]){ //相同位置相同字母个数
                cnt++;
                if(cnt<=n-t) ans[i]=s1[i]-'a'; //有可能相同字母个数多余n-t个字母
            }
        }
        if(n>cnt+2*t) { //不可能的构造
            printf("-1\n");
            continue;
        }
        //printf("n-t-cnt=%d\n",n-t-cnt);
        int num=0,end=-1;
        for(int i=0;i<n;i++){ //从s1找n-cnt-t个位置使得ans和s1相同
            if(num>=n-t-cnt) break; //num是已经找的位置的个数,>=是因为n-t-cnt可能小于0
            if(ans[i]!=-1) continue;
            num++;
            ans[i]=s1[i]-'a'; //ans[i]和s1[i]相同
            end=i;
        }
        num=0;
        for(int i=end+1;i<n;i++){ //从s2找n-cnt-t个位置使得ans和s2相同
            if(num>=n-t-cnt) break;
            if(ans[i]!=-1) continue;
            num++;
            ans[i]=s2[i]-'a';
            end=i;
        }
        for(int i=end+1;i<n;i++){ //在ans的剩余位置应是每个字母都与s1,s2的相应位置字母不同
            if(ans[i]!=-1) continue;
            int vis[30];
            memset (vis,0,sizeof(vis)); //标记s1,s2相应位置出现的字母
            vis[s1[i]-'a']=vis[s2[i]-'a']=1;
            for(int j=0;j<30;j++){
                if(!vis[j]){
                    ans[i]=j;
                    break;
                }
            }
        }
        for(int i=0;i<n;i++){
            printf("%c",ans[i]+'a');
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值