题目链接: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;
- }
-
- 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]);
-
- 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;
- }