Word
题目大意
给你几个字符串,你要你找一个长度为 l 的串。
保证它可以跟每个字符串匹配,保证这个串有且只有一个。
然后匹配就是字符串存在一个长度为 l 的子串跟它一一匹配不想到的位数不超过 d 个,d 给出。
思路
这题其实可以直接暴力。
就直接选一个字符串(选最短的更优),先枚举子串,然后直接拿这个子串直接去匹配,然后如果不行就换一个字符,换到次数上限就退出。
然后是可以过的,选最短的还跑得挺快。
代码
#include<cstdio>
#include<bitset>
#include<cstring>
using namespace std;
int l, d, sn[31], minn, minx, b[31][55];
char a[31][55];
int ck[11], n;
bool yes;
void dfs(int uc, int x) {
if (uc > d) return ;
yes = 1;
for (int i = 2; i <= n; i++) {//匹配
int df = 101;
for (int j = 1; j + l - 1 <= sn[i]; j++) {
int num = 0;
for (int k = 1; k <= l; k++)
if (ck[k] != b[i][j + k - 1]) {
num++;
if (num >= df) break;
}
df = min(df, num);
}
if (df > d) {
yes = 0;
break;
}
}
if (yes) return ;
for (int i = x; i <= l; i++) {//换一个字符
int rem = ck[i];
for (int j = 0; j <= 26; j++) {
if (rem == j) continue;
ck[i] = j;
dfs(uc + 1, i + 1);
if (yes) return ;
ck[i] = rem;
}
}
}
void write() {
for (int i = 1; i <= l; i++)
if (ck[i] == 26) putchar(' ');
else putchar(ck[i] + 'a');
}
int main() {
// printf("%.3lf", (sizeof(t)) / 1024.0);
minn = 100; minx = 0;
scanf("%d %d", &l, &d);
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
sn[i] = 0;
a[i][sn[i] + 1] = getchar();
while (a[i][sn[i] + 1] != ' ' && (a[i][sn[i] + 1] < 'a' || a[i][sn[i] + 1] > 'z')) a[i][sn[i] + 1] = getchar();
while (a[i][sn[i] + 1] == ' ' || (a[i][sn[i] + 1] >= 'a' && a[i][sn[i] + 1] <= 'z')) {
sn[i]++;
a[i][sn[i] + 1] = getchar();
}
a[i][sn[i] + 1] = 0;
for (int j = 1; j <= sn[i]; j++)
if (a[i][j] == ' ') b[i][j] = 26;
else b[i][j] = a[i][j] - 'a';
if (sn[i] < minn) {
minn = sn[i];
minx = i;
}
}
for (int i = 1; i <= sn[1]; i++)//根据最小的建立初始串,这样可以很快
swap(b[1][i], b[minx][i]);
swap(sn[1], sn[minx]);
for (int i = l; i <= sn[1]; i++) {
for (int j = i - l + 1; j <= i; j++)
ck[j - i + l] = b[1][j];
dfs(0, 1);
if (yes) {
write();
return 0;
}
}
return 0;
}