【字串 暴力】Word
阿新 • • 發佈:2021-08-13
暴力
題面
有k個字串{S1,S2,…,Sk},其中的每個字元不是空格,就是26個小寫英文字母中的一個。對於常數 l和d,我們的目標是從這k個字串中得出一個(l,d)-樣詞,它是一個長度為l的字串W=W[1]W[2]...W[l],它的每個字元必須符合下面的條件:
每個字串Si(i=1,2,…,k)都有一個長度為l的子串X=X[1]X[2]...X[l],X和W的出錯率小於或等於d。(X和W的出錯率是(X[j],W[j])的對數,其中,X[j]<>W[j],j=1,2,…,l)
在這個任務中,給你 l,d和一組字串;你要從中得出一個(l,d)-樣詞。你可以預設(l,d)-樣詞是存在的,而且是唯一的。
例1
如下3個字串,相對應的(3,0)-樣詞是“oil”:
oil is expensive
we have three oilers
be more oily
例2
如下4個字串,相對應的(5,1)-樣詞是“apple”:
you have two applas
i am an ppple
we are acples
adples are good for health
思路
分析一下暴力演算法的時間複雜度,會爆炸。
但是跑不滿。
程式碼
#pragma GCC optimize(2) #pragma GCC optimize("Ofast") #include <cstdio> #include <cstring> #include <iostream> #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) int l, d, k; int len[31]; char s[31][51], tmp[51]; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; struct Trie { int trie[1501][28], cnt; void insert(int rt, int l, int r) { int p = 0, tmp; for (int i = l; i <= r; i++) { if (s[rt][i] != ' ') tmp = s[rt][i] - 96; else tmp = 27; if (!trie[p][tmp]) trie[p][tmp] = ++cnt; p = trie[p][tmp]; } } int check(int dep, int p, int sum) { if (sum > d) return 0; if (dep == l) return 1; int now, res = 0; if (tmp[dep] == ' ') now = 27; else now = tmp[dep] - 96; for (int i = 1; i <= 27; i++) if (trie[p][i]) res |= check(dep + 1, trie[p][i], sum + 1 - (i == now)); return res; } } tree[31]; inline bool isok (char ch) { return isalpha(ch) || ch == ' '; } int reads (char *s) { char ch = getchar(); int p = -1; while (!isok(ch)) ch = getchar(); while (isok(ch)) s[++p] = ch, ch = getchar(); s[++p] = 0; return p; } int main() { scanf("%d %d %d\n", &l, &d, &k); int mm = 1; for (int i = 1; i <= k; i++) { len[i] = reads(s[i]); if (len[i] < len[mm]) mm = i; } std::swap(s[mm], s[1]); std::swap(len[mm], len[1]); for (int i = 2; i <= k; i++) for (int j = 0; j < len[i] - l + 1; j++) tree[i].insert(i, j, j + l - 1); int flag, tmpf; for (int i = 0; i < len[1] - l + 1; i++) { int L = i, R = i + l - 1; flag = 0; for (int j = L; j <= R; j++) tmp[j - L] = s[1][j]; if (d == 1) { for (int a = 0; a < l; a++) for (int sa = 1; sa <= 27; sa++) { char ch = tmp[a]; if (sa == 27) tmp[a] = ' '; else tmp[a] = (char)sa + 96; tmpf = 1; for (int j = 2; j <= k; j++) if (!tree[j].check(0, 0, 0)) { tmpf = 0; break; } flag |= tmpf; if (flag) return !printf("%s", tmp); tmp[a] = ch; } } else if (d == 2) { for (int a = 0; a < l; a++) for (int b = a + 1; b < l; b++) for (int sa = 1; sa <= 27; sa++) for (int sb = 1; sb <= 27; sb++) { char cha = tmp[a], chb = tmp[b]; if (sa == 27) tmp[a] = ' '; else tmp[a] = (char)sa + 96; if (sb == 27) tmp[b] = ' '; else tmp[b] = (char)sb + 96; tmpf = 1; for (int j = 2; j <= k; j++) if (!tree[j].check(0, 0, 0)) { tmpf = 0; break; } flag |= tmpf; if (flag) return !printf("%s", tmp); tmp[a] = cha, tmp[b] = chb; } } else { flag = 1; for (int j = 2; j <= k; j++) if (!tree[j].check(0, 0, 0)) { flag = 0; break; } if (flag) return !printf("%s", tmp); } } }
坑
讀入用scanf或getchar比較穩