CF 903E - Swapping Characters 暴力 思维

题意:

给你k个串,每个串长度都是n,现在问你是否可能这些串是同一个串交换两个位置的字符所产生的,输出这个原串。

k <= 2500, n <= 5000, k * n <= 5000

题解:

一开始我想的是,对k个串,全部n^2交换一下,然后hash存在map里面,看哪些串出现了k次,这些串是可以的,

但是复杂度是O(k * n^{2} * log(n^{2})),还是不能过。

然后我想,只要对第一个串进行n^{2}交换即可,但是交换以后对每个串又要用O(n)时间计算差别,复杂度是O(n^{3} * k)

其实计算差别可以用O(1)时间,只要预处理一下所有串与s[1]的差别即可,所以复杂度是O(n^2k)

s1交换两字符后,如果这个是原串,那么后面的串与他的差别要么是2,要么是0,并且可以是0的条件是原串存在两个相同字符。

原串存在的必要条件还有这k个串字符集相同。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif

#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;

const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 5e3 + 5;

char s[MAXN][MAXN];

int num[MAXN][26];
int dif[MAXN];
int dif2[MAXN];


int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    int k, n;
    int f = 0, ok = 1;
    scanf ("%d %d", &k, &n);
    for (int i = 1; i <= k; i++) scanf ("%s", s[i]);
    for (int i = 1; i <= k; i++) {
        for (int j = 0; j < n; j++) num[i][s[i][j] - 'a']++;
        for (int j = 0; j < 26; j++) if (num[i][j] != num[1][j]) ok = 0;
    }
    if (!ok) return 0 * puts ("-1");
    for (int i = 0; i < 26; i++) if (num[1][i] > 1) f = 1;

    for (int i = 2; i <= k; i++)
        for (int j = 0; j < n; j++)
            if (s[i][j] != s[1][j]) dif[i]++;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int can = 1;
            for (int l = 2; l <= k; l++) dif2[l] = dif[l];
            for (int l = 2; l <= k; l++) {
                if (s[1][i] != s[l][i]) dif2[l]--;
                if (s[1][j] != s[l][i]) dif2[l]++;
                if (s[1][j] != s[l][j]) dif2[l]--;
                if (s[1][i] != s[l][j]) dif2[l]++;
                if (dif2[l] != 2) {
                    if(!f || dif2[l] != 0) can = 0;
                }
            }
            if(can) {
                swap(s[1][i], s[1][j]);
                return 0 * printf("%s\n", s[1]);
            }
        }
    }
    puts("-1");

    return 0;
}

猜你喜欢

转载自blog.csdn.net/c6376315qqso/article/details/82701197