http://codeforces.com/contest/903/problem/E
题意是,对于每个字符串都要交换两个位置的字符(id),使得结果所有字符串是一样的,输出那个字符串。
正解是,先比较两个字符串,如果他们不同的位置 > 4那就是不行的了
有4个不同的还是可行的,比如:
abab
baba
因为每个字符串都有一次交换机会,所以可以变成
baab即可
如果小于4,那么暴力枚举每一个不同的位置,和任意一个位置交换,暴力check,复杂度5000^2
我的渣渣做法。
因为n*k<5000
预处理每一个字符串,所有交换情况后得到字符串的hash值,知道原串的hash值,交换两个字符后,得到的hash值可以O(1)搞出来
然后相当于给k个数组,问是否存在一个数字在这k个数组中都存在过。
复杂度n^2 log n
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; const int maxn = 5000 + 2; char str[maxn][maxn]; unsigned long long int po[maxn]; const int seed = 131; int cnt[maxn], DFN; struct Node { unsigned long long int val; int one, two; Node(unsigned long long int _val, int _one, int _two) { val = _val, one = _one, two = _two; } bool operator < (const struct Node & rhs) const { return val < rhs.val; } }; vector<Node> vc[maxn]; void work() { int k, n; scanf("%d%d", &k, &n); for (int i = 1; i <= k; ++i) scanf("%s", str[i] + 1); if (k == 1) { swap(str[1][1], str[1][2]); printf("%s ", str[1] + 1); printf(" "); return; } for (int i = 1; i <= k; ++i) { unsigned long long int now = 0; bool can = false; DFN++; for (int j = 1; j <= n; ++j) { now = now * seed + str[i][j]; can |= cnt[str[i][j]] == DFN; cnt[str[i][j]] = DFN; } if (can) vc[i].push_back(Node(now, 1, 1)); for (int j = 1; j <= n; ++j) { for (int f = j + 1; f <= n; ++f) { if (str[i][j] == str[i][f]) { if (can) continue; can = true; } unsigned long long int ha = now - str[i][j] * po[n - j] - str[i][f] * po[n - f] + str[i][f] * po[n - j] + str[i][j] * po[n - f]; vc[i].push_back(Node(ha, j, f)); // swap(str[i][j], str[i][f]); // cout << str[i] + 1 << " " << ha << endl; // swap(str[i][j], str[i][f]); } } // cout << endl; sort(vc[i].begin(), vc[i].end()); } // for (int i = 1; i <= k; ++i) { // for (int j = 0; j < vc[i].size(); ++j) { // cout << vc[i][j].val << " "; // } // cout << endl; // } for (int i = 0; i < vc[1].size(); ++i) { int t = 1; for (int j = 2; j <= k; ++j) { if (vc[1][i].val > vc[j].back().val) break; int pos = lower_bound(vc[j].begin(), vc[j].end(), vc[1][i]) - vc[j].begin(); if (vc[j][pos].val != vc[1][i].val) break; t++; } if (t == k) { int id1 = vc[1][i].one, id2 = vc[1][i].two; swap(str[1][id1], str[1][id2]); printf("%s ", str[1] + 1); return; } } printf("-1 "); } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif po[0] = 1; for (int i = 1; i <= maxn - 2; ++i) po[i] = po[i - 1] * seed; work(); return 0; }