前綴樹(shù)小試:字模式

原題地址:字模式

給定一個(gè)模式串pattern和一個(gè)字符串str,請(qǐng)問(wèn)str和pattern是否遵循相同的模式钥顽。
這里遵循模式指的是一個(gè)完全匹配义屏,即在pattern中的每個(gè)不同的字母和str中每個(gè)非空的單詞之間有一個(gè)雙向映射的模式對(duì)應(yīng)。

您可以認(rèn)為模式串pattern只包含小寫(xiě)字母蜂大,而str包含由單個(gè)空間分隔的小寫(xiě)單詞組成闽铐。

因?yàn)橐灰粚?duì)應(yīng)的關(guān)系,所以要雙向映射奶浦,所以需要兩個(gè)map: 一個(gè)從pattern的字符到對(duì)應(yīng)的單詞兄墅,一個(gè)從單詞到字符。

這里我沒(méi)有使用系統(tǒng)的map,而是實(shí)現(xiàn)了一個(gè) 前綴樹(shù) 來(lái)練練手澳叉,對(duì)于一個(gè)前綴樹(shù)隙咸,一個(gè)節(jié)點(diǎn)可以和一個(gè)單詞做一一對(duì)應(yīng)的映射沐悦,對(duì)應(yīng)的單詞就是從跟沿著路徑到這個(gè)節(jié)點(diǎn)的那個(gè)單詞。所以可以在這個(gè)節(jié)點(diǎn)里存入跟單詞對(duì)應(yīng)的數(shù)據(jù)五督,就可以實(shí)現(xiàn)從單詞到這個(gè)數(shù)據(jù)的映射藏否,所以這里存入字符,實(shí)現(xiàn)從單詞到pattern的字符的映射充包。

從字符到單詞的映射副签,有多個(gè)方案:

  1. unordered_map<char, string>,用char做key, word做value
  2. 因?yàn)槎际切?xiě)字母误证,所以可以用 string[26]來(lái)標(biāo)記继薛,string[c-'a']就可以得到字符c的word,比較
  3. 因?yàn)榍熬Y樹(shù)里節(jié)點(diǎn)跟單詞一一對(duì)應(yīng)愈捅,所以可以直接存入節(jié)點(diǎn)遏考,結(jié)合2的思路就是:TrieNode[26]. 相比2的好處是,比較單詞相等不用string.compare了蓝谨,直接比較兩個(gè)節(jié)點(diǎn)是否相等就可以了灌具。前綴樹(shù)是節(jié)點(diǎn)不會(huì)刪除,讓這一點(diǎn)成為了可能譬巫。這樣做復(fù)雜度直接從O(N*L)到了O(N)咖楣,L是字符串的平均長(zhǎng)度。

using namespace std;

namespace TFDataStruct {
    template<class T>
    class Trie{
    public:
        struct TrieNode{
            char ch;
            //對(duì)應(yīng)的字符串的個(gè)數(shù)
            uint32_t mark = 0;
            T relateData;  //做額外的數(shù)據(jù)處理
            TrieNode *parent = nullptr;
            unordered_map<char, TrieNode*> childern;
        };
        struct TrieNodeVisitor{
            typedef void (*VisitFunc)(TrieNode *node, string &word, int idx);
            VisitFunc visitF;
            TrieNodeVisitor(VisitFunc visitF):visitF(visitF){};
        };
    private:
    public:
        TrieNode root;
        
        Trie(){};
        Trie(vector<string> &words){
            for (auto &w : words){
                insert(w, nullptr);
            }
        }
        
        /** 插入一個(gè)元素芦昔,同時(shí)最后的節(jié)點(diǎn) */
        TrieNode *insert(string &word, TrieNodeVisitor visitor = nullptr){
            TrieNode *node = &root;
            int idx = 0;
            while (idx<word.length()) {
                auto &next = node->childern[word[idx]];
                if (next == nullptr) {
                    next = new TrieNode();
                    next->ch = word[idx];
                    next->parent = node;
                }
                node = next;
                if (visitor.visitF) visitor.visitF(node, word, idx);
                
                idx++;
            }
            node->mark++;
            
            return node;
        }
        
        int count(string &word){
            TrieNode *node = &root;
            int idx = 0;
            while (idx<word.length()) {
                auto &next = node->childern[word[idx]];
                if (next == nullptr) {
                    return 0;
                }
                node = next;
                idx++;
            }
            
            return node->mark;
        }
        
        bool exist(string &word){
            return count(word)>0;
        }
    };
}


class Solution {
public:
    /**
     * @param pattern: a string, denote pattern string
     * @param teststr: a string, denote matching string
     * @return: an boolean, denote whether the pattern string and the matching string match or not
     */
bool wordPattern(string &pattern, string &teststr) {
    teststr.push_back(' ');
    
    //1. 前綴樹(shù)記錄的是單詞到字符的對(duì)應(yīng)關(guān)系诱贿,每個(gè)節(jié)點(diǎn)唯一對(duì)應(yīng)一個(gè)單詞(即從跟到這個(gè)節(jié)點(diǎn)的路徑拼起來(lái)的單詞),所以用節(jié)點(diǎn)存儲(chǔ)單詞映射的字符;
    //2. markC2W[c]表示c這個(gè)字符映射的單詞咕缎,又因?yàn)楣?jié)點(diǎn)和單詞的一一對(duì)應(yīng)關(guān)系珠十,所以把單詞對(duì)應(yīng)的節(jié)點(diǎn)存入
    TFDataStruct::Trie<char> trieW2C;
    TFDataStruct::Trie<char>::TrieNode* charNodes[256];
    memset(charNodes, 0, sizeof(charNodes));
    
    //3. 因?yàn)橐灰粚?duì)應(yīng)的關(guān)系,1和2剛好是兩個(gè)方向
    
    int start=-1, i = 0;
    int wordIdx = 0;
    for (auto &c : teststr){
        
        if (start<0) {
            if (c!=' ') {
                start = i;
            }
        }else{
            if (c==' ') {
                auto str = teststr.substr(start, i-start);
                auto node = trieW2C.insert(str);
                
                auto charNode = charNodes[pattern[wordIdx]];
                if (charNode == nullptr) {
                    if (node->relateData>0) {
                        return false;
                    }
                }else if (node != charNode) {
                    return false;
                }
                
                node->relateData = pattern[wordIdx];
                charNodes[pattern[wordIdx]] = node;
                
                start = -1;
                wordIdx++;
            }
        }
        
        i++;
    }
    
    return true;
}
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凭豪,一起剝皮案震驚了整個(gè)濱河市焙蹭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嫂伞,老刑警劉巖孔厉,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異帖努,居然都是意外死亡撰豺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)拼余,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)郑趁,“玉大人,你說(shuō)我怎么就攤上這事姿搜」讶螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵舅柜,是天一觀的道長(zhǎng)梭纹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)致份,這世上最難降的妖魔是什么变抽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮氮块,結(jié)果婚禮上绍载,老公的妹妹穿的比我還像新娘。我一直安慰自己滔蝉,他們只是感情好击儡,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蝠引,像睡著了一般熬丧。 火紅的嫁衣襯著肌膚如雪乍楚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音盾沫,去河邊找鬼。 笑死奸远,一個(gè)胖子當(dāng)著我的面吹牛灌危,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冒窍,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼递沪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了超燃?” 一聲冷哼從身側(cè)響起区拳,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎意乓,沒(méi)想到半個(gè)月后樱调,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡届良,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年笆凌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片士葫。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乞而,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慢显,到底是詐尸還是另有隱情爪模,我是刑警寧澤欠啤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站屋灌,受9級(jí)特大地震影響洁段,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜共郭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一祠丝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧除嘹,春花似錦写半、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至龙考,卻和暖如春蟆肆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晦款。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工炎功, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缓溅。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓蛇损,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坛怪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子淤齐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言 最先接觸編程的知識(shí)是在大學(xué)里面更啄,大學(xué)里面學(xué)了一些基礎(chǔ)的知識(shí),c語(yǔ)言居灯,java語(yǔ)言祭务,單片機(jī)的匯編語(yǔ)言等;大學(xué)畢...
    oceanfive閱讀 3,044評(píng)論 0 7
  • 一怪嫌、正則表達(dá)式的用途(搜索和替換) 1.1.正則表達(dá)式(regular expression,簡(jiǎn)稱regex)是一...
    IIronMan閱讀 10,102評(píng)論 0 14
  • python的re模塊--細(xì)說(shuō)正則表達(dá)式 可能是東半球最詳細(xì)最全面的re教程,翻譯自官方文檔,因?yàn)楣俜轿臋n寫(xiě)的是真...
    立而人閱讀 22,833評(píng)論 4 46
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,367評(píng)論 0 5
  • 小時(shí)候放假是為了盼著回家看電視岩灭,再后來(lái)是為了和朋友出去旅行拌倍,而如今我卻格外的想家。 五一假期,本來(lái)不打算回家柱恤。因?yàn)?..
    52b22a640e0e閱讀 291評(píng)論 0 0