Educational Codeforces Round 34 E Swapping Characters

E Swapping Characters

We had a string s consisting of n lowercase Latin letters. We made k copies of this string, thus obtaining k identical strings s1, s2, …, sk. After that, in each of these strings we swapped exactly two characters (the characters we swapped could be identical, but they had different indices in the string).

You are given k strings s1, s2, …, sk, and you have to restore any string s so that it is possible to obtain these strings by performing aforementioned operations. Note that the total length of the strings you are given doesn’t exceed 5000 (that is, k·n ≤ 5000).

Input
The first line contains two integers k and n (1 ≤ k ≤ 2500, 2 ≤ n ≤ 5000, k · n ≤ 5000) — the number of strings we obtained, and the length of each of these strings.

Next k lines contain the strings s1, s2, …, sk, each consisting of exactly n lowercase Latin letters.

Output
Print any suitable string s, or -1 if such string doesn’t exist.

Examples
input
3 4
abac
caab
acba
output
acab
input
3 4
kbbu
kbub
ubkb
output
kbub
input
5 4
abcd
dcba
acbd
dbca
zzzz
output
-1
Note
In the first example s1 is obtained by swapping the second and the fourth character in acab, s2 is obtained by swapping the first and the second character, and to get s3, we swap the third and the fourth character.

In the second example s1 is obtained by swapping the third and the fourth character in kbub, s2 — by swapping the second and the fourth, and s3 — by swapping the first and the third.

In the third example it’s impossible to obtain given strings by aforementioned operations.

这道题就是给你n个长度为k的字符串,然后这几个字符串每两个都将下标不同的的两个字符进行了交换,求原字符。这道题学到了新姿势:汉明距离,就是两个字符串不同字符个数的值。这道题首先要保证每个字符串的字符种类和个数一样,然后暴力交换每两个字符,复杂度为K^2,对于每次交换,求最新的汉明距离,然后比较汉明距离,如果交换后的这个字符串是答案,那么两个字符串的汉明距离只有两种情况:1.汉明距离为2,交换了两个不同的字符。2.汉明距离为0,并且这个字符串中有相同字符,那么可以认为是将这两个相同字符进行了交换,最后的字符串相等。

#include<bits/stdc++.h>
using namespace std;
using LL=int64_t;
const int INF=0x3f3f3f3f;
const int maxn=5005;
string s[maxn];
int ham[maxn],num1[30],num2[30];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,k;
    cin>>n>>k;
    int flag=0;
    for(int i=1;i<=n;i++) cin>>s[i];
    memset(ham,0,sizeof(ham));
    for(int i=2;i<=n;i++) {
        for(int j=0;j<k;j++) {
            if(s[1][j]!=s[i][j]) ham[i]++;
        }
    }
    memset(num1,0,sizeof(num1));
    for(int i=0;i<k;i++) num1[s[1][i]-'a']++;
    for(int i=0;i<26;i++) if(num1[i]>1) flag=1;
    for(int i=2;i<=n;i++) {
        memset(num2,0,sizeof(num2));
        for(int j=0;j<k;j++) {
            num2[s[i][j]-'a']++;
        }
        for(int j=0;j<26;j++) {
            if(num1[j]!=num2[j]) {
                cout<<-1;
                return 0;
            }
        }
    }
    for(int i=0;i<k;i++){
        for(int j=i+1;j<k;j++) {
            int num=0;
            for(int k=1;k<=n;k++) {
                int cnt=ham[k];
                cnt-=(s[1][i]!=s[k][i]);
                cnt-=(s[1][j]!=s[k][j]);
                cnt+=(s[1][i]!=s[k][j]);
                cnt+=(s[1][j]!=s[k][i]);
                if((cnt==0&&flag)||cnt==2) num++;
                else break;
            }
            if(num==n) {
                swap(s[1][i],s[1][j]);
                cout<<s;
                return 0;
            }
        }
    }
    cout<<-1;
    return 0;
}

这里求更新后的汉明距离也是个小技巧,最原始的汉明距离减去这两个字符的贡献再加上更新后的贡献。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值