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 102626 个子串)

然后将其与别的子串一一比较

因为答案唯一的,所以求出一个答案后可以直接退出程序

我这里求答案的方式

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(暴力)

2021.8.13提高B组模拟5T2 Crisis(小根堆)

2017.12.09NOIP提高组模拟赛A组

2017.07.16【NOIP提高组】模拟赛B组 卫星照片 题解