UVa 200
題目
http://domen111.github.io/UVa-Easy-Viewer/?200
給定一群字串,這群字串是依照某種字母順序的排序由小到大排序而成的
字母都只有大寫英文字母,請找出所有出現過的字母由小到大排序後的樣子
想法
因為這題是給定兩元素之間的關係,然後求出排序後的樣子,所以可以想到用拓樸排序
透過比較相鄰兩字串之間第一個不同的字元,就可以找到一組關係式,根據這個關係我們可以在兩個元素之間建立一條邊,並且記錄下連到的元素入度大小
每次找到入度為 $0$ 的元素輸出,並且將下一個連接到的元素入度皆減 $1$
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include<iostream> using namespace std; string pre, now; int in[26], used[26], tot=0; bool edge[26][26]; int main(){ for(int i=0 ; i<26 ; i++){ in[i] = 0; for(int j=0 ; j<26 ; j++){ edge[i][j] = false; } }
cin>>pre; for(int i=0 ; i<pre.size() ; i++){ if(!used[pre[i]-'A']){ used[pre[i]-'A']++; tot++; } } while(cin>>now && now!="#"){ for(int i=0 ; i<now.size() ; i++){ if(!used[now[i]-'A']){ used[now[i]-'A']++; tot++; } } for(int i=0 ; i<pre.size() && i<now.size() ; i++){ if(now[i] != pre[i]){ if(!edge[pre[i]-'A'][now[i]-'A']){ in[now[i]-'A']++; edge[pre[i]-'A'][now[i]-'A']=true; } break; } } pre=now; }
for(int i=0 ; i<tot ; i++){ for(int j=0 ; j<26 ; j++){ if(in[j] == 0 && used[j]){ in[j]--; cout<<(char)(j+'A'); for(int k=0 ; k<26 ; k++){ if(j==k) continue; if(edge[j][k]){ in[k]--; } } } } } cout<<"\n"; return 0; }
|
時間複雜度分析
輸入時間複雜度為 $O(\sum{|now|})$
假設 $n = 26$
拓樸排序時間複雜度最差為 $O(n^3)$
總時間複雜度約為 $O(\sum{|now|} + n^3)$