2021.8.13提高B组模拟5T3 Word (暴力)
Posted SSL_LKJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.8.13提高B组模拟5T3 Word (暴力)相关的知识,希望对你有一定的参考价值。
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
输入样例
输入文件第一行有两个整数 l和d,中间有一个空格,其中1<=l<=10,0<=d<=2。第二行有一个整数k,1<=k<=30。剩下的k行分别是k个字符串,每个字符串的长度最多是50。
5 1
4
you have two applas
i am an ppple
we are acples
adples are good for health
输出样例
输出文件仅有一行包含有一个长度为l的字符串,这个字符串是输入文件中字符串集的(l,d)-样词。可以保证,输入数据总是有且只有一个(l,d)-样词。
apple
题目数据
1<=l<=10,0<=d<=2
解题思路
硬核暴力求解
先将每个字符串中长度为 l l l 的都取出来
每个子串均可以在允许距离(<=d)的范围内变出最多为 10 ∗ 26 ∗ 26 10*26*26 10∗26∗26 个子串)
然后将其与别的子串一一比较
因为答案是唯一的,所以求出一个答案后可以直接退出程序
我这里求答案的方式:
1.先求出合法的k个字符串
2.每一位的答案就是当前位置上在k个字符串中出现次数最多的字符
例如题目样例:
最后求出来的 k 个字符串必然是
appla
ppple
acple
adple
那第一位出现最多的是‘a’,第二位是**‘p’,第三位是‘p’,第四位是‘l’**,第五位是 ‘e’
答案就是 “apple”
3.答案求出来后,要和前面的k个字符串一一比较,判断是否合法
注:输入时的“换行符”!(比赛丢了80就出在这)
AC代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int l,d,k,t,kk,mmin=55,b[55],num[55][30];
string s,ss[35][55],sss[35],ssss[100005];
bool check(string s1,string s2)//比较
{
int oo=0;
for(int i=0;i<l;i++)
if(s1[i]!=s2[i])oo++;
if(oo<=d)return true;
return false;
}
void dfs(int x,string s,int now,string sx)//造字符串(x为有多少个不同的,s为要修改的字符串,now为当前位置,sx为造出来的字符串)
{
if(now==l){ssss[++t]=sx;return;}
dfs(x,s,now+1,sx+s[now]);
if(x<d)
{
for(int i=0;i<26;i++)
if(s[now]!=char(i+97))
dfs(x+1,s,now+1,sx+char(i+97));
}
}
int main()
{
scanf("%d%d",&l,&d);
scanf("%d",&k);
getline(cin,s);
for(int i=1;i<=k;i++)//求出每个字符串的长度为l的字符串
{
getline(cin,s);
int len=s.size();
for(int j=0;j<len;j++)
if(s[j]!=' ')
{
int o=1;
string x;
x=s[j];
while(s[o+j]!=' '&&o<l&&o+j<len)
{
x+=s[o+j];
o++;
}
if(o==l)ss[i][++b[i]]=x;
}
if(b[i]<mmin)mmin=b[i],kk=i;
}
for(int i=1;i<=mmin;i++)
{
int ook=0,tot=0;
sss[++tot]=ss[kk][i];
t=0;
dfs(0,ss[kk][i],0,"");//造字符串
for(int j=1;j<=k;j++)
{
if(j!=kk)
{
int ok=1;
for(int xx=1;xx<=t;xx++)//比较
{
int oook=0;
for(int a=1;a<=b[j];a++)
if(check(ssss[xx],ss[j][a]))
{
ok=0;
oook=1;
sss[++tot]=ss[j][a];
break;
}
if(oook==1)break;
}
if(ok)break;
}
if(j==k)ook=1;
}
if(ook)//求答案
{
string sxx="";
memset(num,0,sizeof(num));
for(int j=1;j<=tot;j++)
for(int a=0;a<l;a++)
num[a][sss[j][a]-97]++;
for(int j=0;j<l;j++)
{
int mmmax=0;
char ch;
for(int a=0;a<26;a++)
if(num[j][a]>mmmax)mmmax=num[j][a],ch=char(a+97);
sxx+=ch;
}
int ookk=1;
for(int j=1;j<=tot;j++)//判断是否合法
if(!check(sxx,sss[j])){ookk=0;break;}
if(ookk)
{
cout<<sxx;
return 0;
}
}
}
return 0;
}
谢谢
以上是关于2021.8.13提高B组模拟5T3 Word (暴力)的主要内容,如果未能解决你的问题,请参考以下文章
2021.8.13提高B组模拟5T1 Brothers(暴力)
2021.8.13提高B组模拟5T2 Crisis(小根堆)
2021.8.13提高B组模拟5T1 Brothers(暴力)