Description
有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
Data Constraint
1<=l<=10,0<=d<=2
Solution
我们发现d是小于2的,所以我们枚举目标串在第一个字符串中的位置。然后枚举修改哪两个位置,然后暴力匹配一下就好。最好用循环来实现,否则时间会很慢……
代码
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=55;
char ch,s[maxn][maxn],b[maxn];
int n,i,t,j,k,l,m,p,a[maxn],f[maxn],num,x,y;
bool bz;
void dg(int num,int x){
int i,j,t,k,l,z=0,y=m+1;bz=false;char ch;
for (i=1;i<=n;i++){
l=m+1;
for (j=1;j<=a[i]-m+1;j++){
t=0;
for (k=1;k<=m;k++)
if (b[k]!=s[i][k+j-1])t++;
l=min(l,t);
}
if (l>p){
bz=true;break;
}
}
if (!bz) return;
if (num>p) return;
for (i=x;i<=m;i++){
for (j=97;j<=122;j++){
if (b[i]==j) continue;
ch=b[i];
b[i]=j;
dg(num+1,i+1);
if (!bz) return;
b[i]=ch;
}
if (b[i]==32) continue;
ch=b[i];
b[i]=32;
dg(num+1,i+1);
if (!bz) return;
b[i]=ch;
}
}
int main(){
// freopen("data.in","r",stdin);
scanf("%d%d%d\n",&m,&p,&n);
for (i=1;i<=n;i++){
scanf("%c",&ch);
while (ch!='\n'){
s[i][++a[i]]=ch;
scanf("%c",&ch);
}
}
for (i=1;i<=a[1]-m+1;i++){
for (j=i;j<=i+m-1;j++)
b[j-i+1]=s[1][j];
dg(1,1);
if (!bz) {
for (j=1;j<=m;j++)
printf("%c",b[j]);
printf("\n");
break;
}
}
}