由所給長度相同的單詞,按位組合出字典序最小的新單詞

一道筆試編程題,想出一個時空複雜度O(N*L)的方法,不知道有沒有更快的 。

題目描述:現給出N個長度爲L的單詞。單詞中僅包含大寫英文字母(A-Z)。

1<=N<=2000

1<=L<=10

你可以從這些單詞中的第n個字母中挑一個作爲你拼詞的第n個字母

比如給出N=3個L=4的單詞:

CAKE

TORN

SHOW

你可以(但不僅限於)拼出以下單詞:

CORN

SAKE

CHRE

但不能拼出:

KARE

因爲N個單詞中,沒有首字母爲K的。

問:按照上述規則,拼出一個與這N個單詞都不相同的新單詞。若無法拼出,則輸出“-”。若有超過一個符合條件的單詞,則輸出字典序最小的那個單詞。

輸入描述:第一行包含2個正整數N、L,分別表示單詞數量與每個單詞長度。
接下來有N行,每行包含一個長度爲L的字符串,字符串中僅包含大與英文字母。

這N個字符串表示給出的N個單詞
輸出描述:
輸出佔一行,僅包含一個字符串,表示題目要求的單詞,若找不到這樣的單詞,則按題目表述出“-”。

#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>
using namespace std;
void moveNext(const vector<bool>&build, char &current) {//O(1)
    current++;
    while (current-'A' < build.size() 
        && build[current-'A'] == false) {
        current++;
    }
}
int englishWord() {
    int N, L;
    while (cin >> N >> L) {
        unordered_set<string> words;
        for (int i = 0; i < N; ++i) {//O(N),保存N個長度爲L的字符串
            string w;
            cin >> w;
            words.emplace(std::move(w));
        }
//保存每個位置出現過的字母,這樣可以鎖定爲26,且不用考慮排序,用std::set<char>也可以
        vector<vector<bool>> exist(L, vector<bool>(26, false));
        vector<char> firstKey(L,'Z'+1);//保存每個位置出現的字典序最小的字母
        for (auto& s : words) {//時間複雜度O(N*L)
            for (int i = 0; i < L; ++i) {
                exist[i][s[i] - 'A'] = true;
                if (s[i]< firstKey[i])
                    firstKey[i] = s[i];
            }
        }
        string res(L, '\0');
        for (int i = 0; i < L; ++i) {//O(L),生成第一個答案
            res[i] = firstKey[i];
        }
        //檢查是否重複,並且自加、進位
        while (words.find(res) != words.end()) {//O(L)
            int pos = L - 1;
            moveNext(exist[pos], res[pos]);//從最後一位開始自加
            while (pos > 0 && res[pos] == 'Z' + 1) {//逐位判斷是否需要進位
                res[pos] = firstKey[pos];
                moveNext(exist[pos - 1], res[pos - 1]);
                pos--;
            }
            if (pos == 0 && res[pos] == 'Z' + 1) {//找完了,全都不符合
                res = "-";
                break;
            }
        }
        cout << res;
    }
    return 0;
}

題給測試用例


3 4
COKE
TARN
SHOW


輸出CAKE,通過

自己的例子


3 5

AAAAA

AAAAB

AAAAC


輸出-,通過


5 5
AAAAA
AAAAB
AAAAC
ABCDE
BBBBF


輸出AAAAE,通過


7 5
AAAAA
AAAAB
AAAAC
AAABA
AAABB
AAABC
AABAA


輸出AABAB,通過


9 3
AAA
AAB
AAC
ABA
ABB
ABC
ACA
ACB
ACC 


輸出-,通過 

 

歡迎打臉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章