NOIP提高组 Word

15 篇文章 0 订阅

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;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值