【NOIP2016提高A组模拟9.9】Word

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

Input

输入文件第一行有两个整数 l和d,中间有一个空格,其中1<=l<=10,0<=d<=2。第二行有一个整数k,1<=k<=30。剩下的k行分别是k个字符串,每个字符串的长度最多是50。

Output

输出文件仅有一行包含有一个长度为l的字符串,这个字符串是输入文件中字符串集的(l,d)-样词。可以保证,输入数据总是有且只有一个(l,d)-样词。

Sample Input

5 1
4
you have two applas
i am an ppple
we are acples
adples are good for health

Sample Output

apple

Data Constraint

1<=l<=10,0<=d<=2

比赛时の想法

在第一个字符串中枚举一段话,再枚举其中的d个错误的地方,在与后面的字符串匹配的时候就可以知道错误的地方应该填什么了(如果合法的话)

var
    s:array[0..35]of string;
    bz:array[0..35]of boolean;
    len,cq:array[0..35]of longint;
    i,j,k,l,n,d,x,y,xx,yy:longint;
    pi:string;
procedure dfs(x:longint;p:string);
var
    i,j,t1,t2,cc:longint;
    cy:string;
    b:boolean;
begin
    if x=k+1 then
    begin
        for i:=1 to k do
        begin
            t1:=0;
            for j:=cq[i] to cq[i]+l-1 do
                if s[i][j]<>p[j-cq[i]+1] then inc(t1);
            if t1>d then exit;
        end;
        writeln(p);
        halt;
    end else
    begin
        for i:=1 to len[x]-l+1 do
        begin
            t1:=0;
            cc:=0;
            cy:=p;
            b:=true;
            for j:=i to i+l-1 do
            begin
                if s[x][j]<>p[j-i+1] then
                begin
                    if bz[j-i+1]=true then
                    begin
                        inc(cc);
                        if cc>d then
                        begin
                            b:=false;
                            break;
                        end;
                        cy[j-i+1]:=s[x][j];
                    end else
                    begin
                        inc(t1);
                        if t1>d then
                        begin
                            b:=false;
                            break;
                        end;
                    end;
                end;
            end;
            if b=false then continue;
            if cy[xx]<>p[xx] then bz[xx]:=false;
            if cy[yy]<>p[yy] then bz[yy]:=false;
            if (t1<d) and (cy[xx]<>p[xx]) then
            begin
                inc(t1);
                cy[xx]:=p[xx];
                bz[xx]:=true;
            end;
            if (t1<d) and (cy[yy]<>p[yy]) then
            begin
                inc(t1);
                cy[yy]:=p[yy];
                bz[yy]:=true;
            end;
            cq[x]:=i;
            dfs(x+1,cy);
            if cy[xx]<>p[xx] then bz[xx]:=true;
            if cy[yy]<>p[yy] then bz[yy]:=true;
        end;
    end;
end;
begin
    //assign(input,'t3.in'); reset(input);
    readln(l,d);
    readln(k);
    for i:=1 to k do readln(s[i]);
    for i:=1 to k do len[i]:=length(s[i]);
    for i:=1 to len[1]-l+1 do
    begin
        pi:='';
        for j:=i to i+l-1 do pi:=pi+s[1][j];
        for x:=0 to l do
            for y:=0 to l do
            if (x<>y) or ((x=0) and (y=0)) then
            begin
                fillchar(cq,sizeof(cq),0);
                cq[1]:=i;
                xx:=x; yy:=y;
                if (d<=1) and (y<>0) then continue;
                if (d=0) and (x<>0) then continue;
                fillchar(bz,sizeof(bz),false);
                bz[x]:=true;
                bz[y]:=true;
                dfs(2,pi);
            end;
    end;
    //close(input);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值