【字符串 暴力】Word
题面
有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比较稳

浙公网安备 33010602011771号