度度熊与排列
Accepts: 1100
Submissions: 3486
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
度熊有一个机器,这个机器有一个 1∼M 的排列 p[1..M] 当作参数,若丢进一个长度为 M 的字符串,此机器会将此字符串重新排列后再输出,重新排列的方式为:原本第 i 个位置的字符会变到第 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 行的字符串代表机器对于第 i 个字符串的输出结果。
-
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
3 1 2
2 4 3 1
1 2 3
-1
Note
第一组询问中, p[1]=3,p[2]=1,p[3]=2p[1]=3,p[2]=1,p[3]=2 是唯一的机器可能的参数。
第二组询问中, p=[2,4,3,1]p=[2,4,3,1] 和 p=[3,4,2,1]p=[3,4,2,1] 都是机器可能的参数,不过 [2,4,3,1][2,4,3,1] 的字典序比 [3,4,2,1][3,4,2,1] 还小,故必须输出 2,4,3,1。
思路:
- 观察发现,在序列sv中的第i项数字确定后,原字符串的第i项必然是新字符串的sv[i]项
- 从1到M逐步构造序列的每一项,如果有字符串不匹配,则从小到大更新的构造sv[i]
- 当sv[i]无法更新时说明没有一个可以匹配到所有字符串的序列,此时返回-1
- 当sv[1~M]都更新完成,打印sv数组即为答案
代码如下:
//1002 #include<iostream> #include<cstring> #include<cstdio> using namespace std; char pre[25][55]; char nxt[25][55]; int v[55],sv[55]; int N,M; int j,k ; char c; bool bfs(int i) { if(i == M)return true; c = pre[0][i]; for(j = 0 ; j < M; j++){ if(c == nxt[0][j] && v[j] == -1){ v[j] = i; sv[i] = j; for(k = 1; k < N;k++){ if(pre[k][i] != nxt[k][sv[i]]){ v[j] = -1;sv[i] = -1; break; }; } if(k != N)continue; if(bfs(i+1))return true; } } return false; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); for(int i = 0 ; i < N;i++){ scanf("%s",pre[i]) ; scanf("%s",nxt[i]) ; } memset(v,-1,sizeof(v)); if(bfs(0)){ for(int i = 0 ; i < M;i++){ printf("%d",sv[i]+1); if(i == M-1) printf(" "); else printf(" "); } }else{ printf("-1 "); } } return 0; }