UVa 10393
題目
http://domen111.github.io/UVa-Easy-Viewer/?10393
給定每個手指在鍵盤上可以輸入的字元
現在有一個人有幾個手指頭受傷沒辦法打特定的字,給一群字串,問所有字串中他可以打出來,並且長度最長的字串有多少個?分別是哪些?
輸出請以字典序大小由小到大輸出,並且每個字串都只能至多出現一次
想法
我們可以用 bit 去分別記錄特定手指可以寫的字
輸入會告訴我們哪些手指不能用,那我們可以先把不能用的手指可以打得字以位元記錄下來,再反轉後就變成可以打的
實作上可以跟所有可行字元組成的數字 xor 來處理
到目前我們有了當前這個人可以打哪些字元這項資訊,那麼最後只需要判斷每個字是否可以被打出來,然後找出最長的長度即可
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| #include<iostream> #include<algorithm> using namespace std; string dict = "qazwsxedcrfvtgb yhnujmik,ol.p;/"; string fig[11] = {"", "qaz", "wsx", "edc", "rfvtgb", " ", " ", "yhnujm", "ik,", "ol.", "p;/"}; string s[1005]; int tbl[128], alltype[32]; int all=0, F, N, cantype, ans, len; bool res[1005];
int str_to_num(string s){ int ret = 0; for(int i=0 ; i<s.size() ; i++){ ret |= (1<<tbl[s[i]]); } return ret; }
int main(){ for(int i=0 ; i<dict.size() ; i++){ tbl[dict[i]] = i; } for(int i=1 ; i<=10 ; i++){ for(int j=0 ; j<fig[i].size() ; j++){ alltype[i] |= (1<<tbl[fig[i][j]]); } all |= alltype[i]; } while(cin>>F>>N){ cantype = ans = len = 0; for(int i=0, f ; i<F ; i++){ cin>>f; cantype |= alltype[f]; } cantype ^= all; for(int i=0 ; i<N ; i++){ cin>>s[i]; } sort(s, s+N); for(int i=0, num, sz ; i<N ; i++){ if(i>0 && s[i] == s[i-1]){ res[i] = false; continue; } num = str_to_num(s[i]); sz = s[i].length(); if((num & cantype) == num){ res[i] = true; if(sz > len){ len = sz; ans = 1; } else if(sz == len){ ans++; } } else{ res[i] = false; } } cout<<ans<<"\n"; for(int i=0 ; i<N ; i++){ if(res[i] && s[i].length() == len){ cout<<s[i]<<"\n"; } } } return 0; }
|
時間複雜度分析
每筆測資輸入時間複雜度為 $O(N)$
每筆測資排序時間複雜度為 $O(NlogN)$
每筆測資找可以被打出來的字串所需時間複雜度為 $O(N)$
每筆測資找答案時間複雜度為 $O(N)$
每筆測資總時間複雜度為 $O(N + NlogN)$