2019百度之星初赛第二场 度度熊与排列

本文介绍了度熊遇到的一个排列问题,他忘记了一个机器的排列参数,只记得参数长度M。通过输入N个字符串及其机器输出,求解度熊记录对应的字典序最小的排列参数。题目提供了解题思路,即暴力模拟检查所有可能的排列,找到满足所有条件的最小字典序排列,若不存在则输出-1。
摘要由CSDN通过智能技术生成

Problem Description

度熊有一个机器,这个机器有一个 1∼M 的排列 p[1..M] 当作参数,若丢进一个长度为 M 的字符串,此机器会将此字符串重新排列后再输出,重新排列的方式为:原本第 iii 个位置的字符会变到第 p[i] 个位置。

举例来说,当 M=3 p[1]=3,p[2]=1,p[3]=2,那么丢 "abc" 进入这个机器后,机器会输出"bca";若丢进的是 "ded",那么机器会输出 "edd"。

某天,度熊不小心忘记这个机器的参数了,只记得参数的长度是 M,于是他丢了 N 长度为 M 的字符串进去,并记录下对于每个字符串机器的输出结果,请你根据这些结果,帮度熊找回这个机器的参数。若有多组参数都满足度熊的记录,请输出字典序最小的排列作为参数。若并不存在任何参数满足度熊的记录,请输出 −1-。

注:对于两个相异的排列a: a[1..M] 和 b[1..M],我们称 a 比 b 小当且仅当 存在一个 i,满足对于所有小于 i 的 j 都有 aj=bj且 ai<bi​​。

Input

有多组询问,第一行包含一个正整数 T 代表有几组询问。

每组询问的第一行包含两个正整数 N,M,分别代表度熊丢进机器的字符串数目以及参数的长度。接下来还有 2×N 行,每行有一个长度为 M 的字符串,当中的第 2×i−1 行的字符串代表度熊丢进去机器的第 i 个字符串,而第 2×i行的字符串代表机器对于第 iii 个字符串的输出结果。

  • 1≤T≤100

  • 1≤N≤20

  • 1≤M≤50

  • 字符串由英文小写字母('a' 至 'z') 组成

Output

对于每一个询问,输出一行,若不存在任何参数满足度熊的记录,这行只包含一个整数 −1。否则这行包含一个排列,代表此机器所有可能的参数中字典序最小的那个。

Sample Input

4
1 3
abc
bca
2 4
aaab
baaa
cdcc
cccd
3 3
aaa
aaa
bbb
bbb
ccc
ccc
1 1
a
z

Sample Output

3 1 2
2 4 3 1
1 2 3
-1

Note
第一组询问中, p[1]=3,p[2]=1,p[3]=2 是唯一的机器可能的参数。

第二组询问中, p=[2,4,3,1]和 p=[3,4,2,1] 都是机器可能的参数,不过 [2,4,3,1]的字典序比 [3,4,2,1] 还小,故必须输出 2,4,3,1。

思路:看到n,m都不太大,感觉可以暴力模拟O(n*m*m)

 

从小到大枚举参数,如果当前参数满足第一组,那么把这个参数代入其他组,如果都符合那就是他了

 

这个参数不满足那就继续找,如果都不满足那就输出-1

 

因为是从小到大枚举的,所以字典序一定是最小的

#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define max(a,b) a>b?a:b
using namespace std;
typedef long long ll;
char s[25][55];
char t[25][55];
int P[55];
bool vis[55];
int n,m;
bool flag;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%s%s",s[i]+1,t[i]+1);
		}
		memset(vis,0,sizeof(vis));
		for(int pos=1;pos<=m;pos++){
			int p=0;
			flag=false;
			for(p=1;p<=m;p++){
				if(!vis[p]&&s[1][pos]==t[1][p]){
					flag=true;
					for(int i=2;i<=n;i++){
						if(s[i][pos]!=t[i][p]){
							flag=false;
							break;
						}
					}
					if(flag){
						P[pos]=p;
						vis[p]=true;
						break;
					} 
				}
			}
			if(!flag) break;
		}
		if(!flag) printf("-1\n");
		else {
			for(int i=1;i<=m;i++){
				printf("%d%c",P[i]," \n"[i==m]);
			}
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值