584C

本文介绍了一道编程题,任务是寻找一个长度为n的字符串s3,使得s3与另外两个长度相同的字符串s1和s2在恰好t个字符上不同。文章提供了两种解题思路并附带了代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


C. Marina and Vasya
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Marina loves strings of the same length and Vasya loves when there is a third string, different from them in exactly t characters. Help Vasya find at least one such string.

More formally, you are given two strings s1s2 of length n and number t. Let's denote as f(a, b) the number of characters in which strings a and b are different. Then your task will be to find any string s3 of length n, such that f(s1, s3) = f(s2, s3) = t. If there is no such string, print  - 1.

Input

The first line contains two integers n and t (1 ≤ n ≤ 1050 ≤ t ≤ n).

The second line contains string s1 of length n, consisting of lowercase English letters.

The third line contain string s2 of length n, consisting of lowercase English letters.

Output

Print a string of length n, differing from string s1 and from s2 in exactly t characters. Your string should consist only from lowercase English letters. If such string doesn't exist, print -1.

Sample test(s)
input
3 2
abc
xyc
output
ayd
input
1 0
c
b
output
-1


解题思路:

题目要寻找与字符串s1,s2差异度为t的字符串,我们观察发现,对于任意位置pos,若s1[pos] = s2[pos],不管ans[pos]是否与之相同,都不会导致ans与s1,s2差异度不同;

若s1[pos] != s2[pos],同样若ans[pos]与之都不同,不会产生影响,但是若ans[pos]与某字符串该位置上的字符相同(假设ans[pos]=s1[pos]),会造成差异度不相等,这时的解决办法是找到下个字符不同的位置k,另ans[k] = s2[k]. 即需要成对的选择s1[pos] != s2[pos]的字符,进行上述操作.


假设字符串s1,s2相同字符数量为same,不同字符数量为diff

1. 通过枚举选择的对数i(0<=i<=diff/2),因为对每对字符进行轮流选择操作会造成1个差异度,所以现有差异度为i;其他的不同字符造成的差异度为diff-2*i;相同字符需要造成的差异度为t-i-(diff-2*i);

#include <stdio.h>
#include <string.h>

using namespace std;

const int maxn = 100024;
char s1[maxn], s2[maxn];

char getdiff(char c){
    for(int i=0; i<26; i++){
        char t = i + 'a';
        if(t != c) return t;
    }
}

char getdiff(char c, char ch){
    for(int i=0; i<26; i++){
        char t = i + 'a';
        if(t != c && t != ch) return t;
    }
}
int main(){
    int n, t;
    scanf("%d%d",&n,&t);
    scanf("%s",s1);
    scanf("%s",s2);

    int diff = 0, same;
    for(int i=0; i<n; i++)
        if(s1[i] != s2[i])
            diff++;
    same = n - diff;

    char ans[maxn];
    int k=0;
    for(int i=0; i<=diff; i+=2){
        int ex = i/2 + (diff-i);//字符不同区域造成的差异度
        if(ex<=t && t<=ex+same){
            bool f = true;
            int need = t - ex;  //字符相同区域不要补充的差异度
            int cnt = i;
            for(int j=0; j<n; j++){
                if(s1[j] == s2[j]){
                    if(need > 0){
                        ans[k++] = getdiff(s1[j]);
                        need--;
                    }else   ans[k++] = s1[j];
                }else{
                    if(cnt > 0){
                        ans[k++] = f ? s1[j] : s2[j];
                        cnt--;
                        f = !f;
                    }else   ans[k++] = getdiff(s1[j],s2[j]);
                }
            }
            ans[k] = 0;
            printf("%s\n",ans);
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}


2. 利用贪心策略解决,不同字符区域可造成差异度的范围为diff-diff/2到diff,若t在此范围内,假设x为进行轮流选择操作的对数,有x + (diff-2*x) = t,推导出x = diff-t;若大于diff,则需要从字符相同区域补充t-diff的差异度.

#include <stdio.h>
#include <string.h>

using namespace std;

const int maxn = 100024;
char s1[maxn], s2[maxn];

char find(char c){
    int i;
    for(i=0; i<26; i++){
        char ch = i+'a';
        if(ch != c)
            return ch;
    }
}

char find(char c, char s){
    int i;
    for(i=0; i<26; i++){
        char ch = i+'a';
        if(ch != c && ch!=s)
            return ch;
    }

}
int main(){
    int n, t, diff, len=0, i;
    scanf("%d%d",&n,&t);
    char ans[maxn];
    int k=0;
    scanf("%s",s1);
    scanf("%s",s2);
    for(i=0; i<n; i++){
        if(s1[i] == s2[i])
            len++;
    }
    diff = n - len;
    if(2*t < diff)
        printf("-1\n");
    else{
        int cnt = diff - t;
        int tmp = t - diff;
        bool flag = false;
        for(int i=0; i<n; i++){
            if(s1[i]==s2[i]){
                if(tmp > 0){
                    ans[k++] = find(s1[i]);
                    tmp--;
                }else   ans[k++] = s1[i];
            }else{
                if(cnt > 0){
                    if(flag){
                        ans[k++] = s1[i];
                        cnt--;
                    }else   ans[k++] = s2[i];

                    flag = !flag;
                }else{
                    ans[k++] = find(s1[i],s2[i]);
                }
            }
        }
        ans[k] = 0;
        printf("%s\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值