Educational Codeforces Round 903E

31 篇文章 0 订阅
19 篇文章 0 订阅

题目链接:http://codeforces.com/contest/903

题意:给出K个串, 每个串长度为N, 问是否可以找到一个模式串, 使得对于任意Si(1<= i < = N),都可以通过交换2个字符(2个字符下标不同,并且必须交换)使其与找到的模式串相同。

题解:很奇妙的解法。

  1:很显然, 一定是这N个串里, 任意S[i]交换(S[i][pos1], S[i][pos2])得到模式串。但是这样从一个串里选2个是C(2,N),然后需要对K个串进行匹配,每次匹配的复杂度是O(N), 所以总体复杂第是N^3*K的, 显然会被数据卡掉。

  2:现在进行优化, 我们可以任找2个不同的串,用数组记录下来这2个串字符不同的位置,不同的数目为tot。 接下来一点很重要如果tot = 1, 则一定无解, 很显然, 如果

tot > 4, 也一定无解很显然,tot = 4的时候比如(caab, acba)4个位置都不同, 但可以找到模式串acab。 接下来就对其中一个串不同的位置与这个串其他位置进行交换这里复杂度就优化成了O(tot*N),然后在O(K*N)进行匹配, 总体复杂度为tot*N^2*K。

#include <bits/stdc++.h>

using namespace std;
const int N = 2507;
string s[N], res;
bool vis[26];
int h[27], n, k, dif[N], tot;
bool solve(int p1, int p2)
{
    tot = 0;
    for(int i = 0;i < n;i ++)  if(s[p1][i] != s[p2][i]) {
        dif[tot++] = i;
    }
    //cout << tot <<endl;
    if(tot == 1 || tot > 4) {
        return false;
    }
    int ok = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 0;i < tot;i ++) {
        for(int j = 0;j < n;j ++) {
            if(j == dif[i]) continue;
            res = s[p1];
            int fg = 1, t1 = dif[i], t2 = j;
            swap(res[t1], res[t2]);
            //cout << t1 << " " << t2 << res <<endl;
            for(int now = 0;now < k;now ++) {
                if(now != p1) {
                    vector<int> vec;
                    for(int p = 0;p < n;p ++) {
                        if(res[p] != s[now][p]) vec.push_back(p);
                    }
                    if(vec.size() == 1 || vec.size() > 2) {
                        fg = 0; break;
                    } else if(vec.size() == 0) {
                        memset(h, 0, sizeof(h));
                        int kk = 0;
                        for(int z = 0;z < n;z ++) {
                            int idx = s[now][z] - 'a';
                            if(h[idx]) {
                                kk = 1;
                            }
                            h[idx] = 1;
                        }
                        if(!kk) {
                            fg = 0; break;
                        }
                    } else {
                        fg &= (res[vec[0]] == s[now][vec[1]] && res[vec[1]] == s[now][vec[0]]);
                        if(!fg) break;
                    }
                }
            }
            if(fg) {
                return 1;
            }
        }
    }
    if(!ok) {
        return false;
    }
}

int main()
{
    std::ios::sync_with_stdio(false), cin.tie(0);
    cin >> k >> n;
    for(int i = 0;i < k;i ++) cin >> s[i];
    for(int i = 0;i < k;i ++) {
        for(int j = i + 1;j < k;j ++) {
            if(s[i] != s[j]) {
                int fg1 = solve(i, j);
                if(fg1) {
                    return cout << res << endl, 0;
                }
                return cout << -1 << endl, 0;
            }
        }
    }
    swap(s[0][0], s[0][1]);
    cout << s[0] << endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值