度度熊與排列[搜索+剪枝]----2019 年百度之星·程序設計大賽 - 初賽二:1002


度度熊與排列

 
 Accepts: 1100
 
 Submissions: 3486
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)
Problem Description

度熊有一個機器,這個機器有一個 1 \sim M1M 的排列 p[1..M]p[1..M] 當作參數,若丟進一個長度為 MM 的字符串,此機器會將此字符串重新排列后再輸出,重新排列的方式為:原本第 ii 個位置的字符會變到第 p[i]p[i] 個位置。

舉例來說,當 M = 3M=3p[1]=3,p[2]=1,p[3]=2p[1]=3,p[2]=1,p[3]=2,那么丟 "abc" 進入這個機器后,機器會輸出"bca";若丟進的是 "ded",那么機器會輸出 "edd"。

某天,度熊不小心忘記這個機器的參數了,只記得參數的長度是 MM,於是他丟了 NN 長度為 MM 的字符串進去,並記錄下對於每個字符串機器的輸出結果,請你根據這些結果,幫度熊找回這個機器的參數。若有多組參數都滿足度熊的記錄,請輸出字典序最小的排列作為參數。若並不存在任何參數滿足度熊的記錄,請輸出 -11

注:對於兩個相異的排列a: a[1..M]a[1..M] 和 b[1..M]b[1..M],我們稱 aa 比 bb 小當且僅當 存在一個 ii,滿足對於所有小於 ii 的 jj 都有 a_j = b_jaj=bj 且 a_i < b_iai<bi

Input

有多組詢問,第一行包含一個正整數 TT 代表有幾組詢問。

每組詢問的第一行包含兩個正整數 N, MN,M,分別代表度熊丟進機器的字符串數目以及參數的長度。接下來還有 2 \times N2×N 行,每行有一個長度為 MM 的字符串,當中的第 2 \times i - 12×i1 行的字符串代表度熊丟進去機器的第 ii 個字符串,而第 2 \times i2×i 行的字符串代表機器對於第 ii 個字符串的輸出結果。

  • 1 \le T \le 1001T100

  • 1 \le N \le 201N20

  • 1 \le M \le 501M50

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

Output

對於每一個詢問,輸出一行,若不存在任何參數滿足度熊的記錄,這行只包含一個整數 -11。否則這行包含一個排列,代表此機器所有可能的參數中字典序最小的那個。

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("\n");
                else printf(" ");
            }
        }else{
            printf("-1\n");
        }
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM