題目大意
已知一種新的火星文的單詞由英文字母(僅小寫字母)組成,但是此火星文中的字母先後順序未知。給出一組非空的火星文單詞,且此組單詞已經按火星文字典序進行好了排序(從小到大),請推斷出此火星文中的字母先後順序。
輸入描述:
一行文本,爲一組按火星文字典序排序好的單詞(單詞兩端無引號),單詞之間通過空格隔開。
輸出描述:
按火星文字母順序輸出出現過的字母,字母之間無其他字符,如果無法確定順序或者無合理的字母排序可能,請輸出"invalid"(無需引號)。
輸入例子1:
z x
輸出例子1:
zx
輸入例子2:
wrt wrf er ett rftt
輸出例子2:
wertf
輸入例子3:
z x z
輸出例子3:
invalid
分析
先把每個單詞取出來,因爲單詞是排好序的,所以臨近兩個單詞,從左邊開始,只看第一個不一樣的字符,轉換爲int型,假設爲a,b,然後如果這兩個數之前沒有比較過,那麼deg[b]++,最後拓撲排序就可以了。主要是怎麼獲得deg[]數組的值。在拓撲排序裏面,隊列裏一開始只加入第一個單詞的第一個字符,其他度爲0的先不加,例如:wf ec ef,我們能比較出w在e前面,c在f前面,但是w和c我們卻不知道順序。
代碼
import java.util.*;
public class Main {
static Scanner sc = new Scanner(System.in);
static int N = 1005;
static String word[] = new String[N];
static int deg[] = new int[30];
static boolean mp[][] = new boolean[30][30];
static boolean vis[] = new boolean[30];
static int cnt = 0;
static int sum = 0;
public static void main(String[] args) {
String str;
str = sc.nextLine();
init();
get_word(str);
get_deg();
tuopu();
}
static void init() {
for(int i = 0; i < N; i++) {
word[i] = ""; // 初始值是null
}
}
static void get_word(String str) { // 把每個單詞取出來
char c;
int num;
for(int i = 0; i < str.length(); i++) {
c = str.charAt(i);
if(c != ' ') {
word[cnt] += c;
num = (int)(c - 'a');
if(vis[num] == false) {
vis[num] = true;
sum++; // 統計出現了多少種字符
}
} else {
cnt++;
}
}
}
static void get_deg() {
int a, b;
for(int i = 0; i < cnt; i++) {
for(int j = 0; j < word[i].length(); j++) {
if(word[i + 1].length() - 1 >= j) {
a = (int)(word[i].charAt(j) - 'a');
b = (int)(word[i + 1].charAt(j) - 'a');
if(a != b) {
if(mp[a][b] == false) { // 確保不會重複
mp[a][b] = true;
deg[b]++;
}
break;
}
}
}
}
}
static void tuopu() {
Queue<Integer> queue = new LinkedList<>();
queue.add((int)(word[0].charAt(0) - 'a'));
int count = 0, tmp;
String ans = "";
while(queue.isEmpty() == false) {
tmp = queue.peek();
queue.remove();
ans += (char)(tmp + 'a');
count++;
for(int i = 0; i < 30; i++) {
if(mp[tmp][i]) {
deg[i]--;
if(deg[i] == 0) {
queue.add(i);
}
}
}
}
if(count != sum) {
System.out.println("invalid");
} else {
System.out.println(ans);
}
}
}