最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C C++算法題解LeetCode1408數(shù)組中的字符串匹配

 更新時(shí)間:2022年10月14日 09:21:10   作者:Junkman丶  
這篇文章主要為大家介紹了C C++算法題解LeetCode1408數(shù)組中的字符串匹配示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

題目描述

題目鏈接:1408. 數(shù)組中的字符串匹配

給你一個(gè)字符串?dāng)?shù)組 words ,數(shù)組中的每個(gè)字符串都可以看作是一個(gè)單詞。請(qǐng)你按 任意 順序返回 words 中是其他單詞的子字符串的所有單詞。

如果你可以刪除 words[j] 最左側(cè)和/或最右側(cè)的若干字符得到 word[i] ,那么字符串 words[i] 就是 words[j] 的一個(gè)子字符串。

提示:

示例 1:

輸入:words = ["mass","as","hero","superhero"]
輸出:["as","hero"]
解釋:"as" 是 "mass" 的子字符串,"hero" 是 "superhero" 的子字符串。
["hero","as"] 也是有效的答案。

示例 2:

輸入:words = ["leetcode","et","code"]
輸出:["et","code"]
解釋:"et" 和 "code" 都是 "leetcode" 的子字符串。

示例 3:

輸入: words = ["blue","green","bu"]
輸出: []

整理題意

題目給定一個(gè)字符串?dāng)?shù)組 words,對(duì)于數(shù)組中的每個(gè)字符串來說,如果該字符串為數(shù)組中其他某個(gè)字符串的子串,那么就將該字符串加入答案字符串?dāng)?shù)組。可以按照任意順序返回該答案數(shù)組。

解題思路分析

注意題目的數(shù)據(jù)提示:題目數(shù)據(jù) 保證 每個(gè) words[i] 都是獨(dú)一無二的。所以不存在兩個(gè)相同的字符串,也避免了互為子字符串的情況。

根據(jù)題目數(shù)據(jù)范圍來看,完全可以采用較為暴力的方法來進(jìn)行解題,枚舉每個(gè)字符串作為子串,檢查是否為其他某個(gè)字符串的子串即可。

優(yōu)化

在字符串匹配的時(shí)候可以采用 KMP 字符串匹配算法來進(jìn)行優(yōu)化時(shí)間復(fù)雜度。

具體實(shí)現(xiàn)

對(duì)于字符串匹配部分可以調(diào)用 string 中的 find() 函數(shù)進(jìn)行匹配 t.find(p)(在字符串 t 中匹配字符串 p,也就是查找字符串 t 中是否包含字符串 p):

  • 此處需要用到 string 庫中的 find() 函數(shù)與 string::npos 參數(shù);

string::npos 參數(shù)是一個(gè)常數(shù),用來表示不存在的位置。

  • stringfind() 返回值是子串的第一個(gè)字符在母串中的位置(下標(biāo)記錄),如果沒有找到,那么會(huì)返回一個(gè)特別的標(biāo)記 string::npos。

可以對(duì)字符串?dāng)?shù)組 words 進(jìn)行排序處理,這樣就可以從最短的字符串開始匹配,且每次往后遍歷匹配,因?yàn)榍懊娴淖址欢ǘ逃诋?dāng)前字符串。

在使用 KMP 字符串匹配算法時(shí)需要注意:

  • KMP 字符串匹配算法的核心思想是 遞歸回溯思想,當(dāng)匹配失敗時(shí)根據(jù) nxt 數(shù)組來進(jìn)行回溯跳轉(zhuǎn);
  • nxt 數(shù)組表示模式串的子串的前綴和后綴相同的最長長度,這樣就可以在匹配的過程中如果遇到不匹配的字符,模式串用 nxt 數(shù)組進(jìn)行遞歸跳轉(zhuǎn)到最長符合的位置進(jìn)行繼續(xù)匹配,從而不需要目標(biāo)串進(jìn)行重復(fù)的往返匹配。
  • 其中需要要注意的一個(gè)技巧是 nxt[0] = -1,在把 nxt 數(shù)組進(jìn)行向右偏移時(shí),第 0 位的值,我們將其設(shè)成了 -1,這只是為了編程的方便,并沒有其他的意義。
  • 還需要注意 nxt 數(shù)組的優(yōu)化,優(yōu)化后在回溯跳轉(zhuǎn)的時(shí)候會(huì)回溯跳轉(zhuǎn)到首次與當(dāng)前字符不一樣字符的位置,避免了跳轉(zhuǎn)到和當(dāng)前字符一樣的位置進(jìn)行重復(fù)判斷。
  • 在實(shí)現(xiàn) getNext() 函數(shù)的時(shí)候需要注意 nxt 數(shù)組溢出問題,可以通過增加 nxt 數(shù)組大小,或減少 getNext() 函數(shù)中循環(huán)遍歷的次數(shù)來防止越界出現(xiàn)的運(yùn)行錯(cuò)誤。
  • 需要注意在 getNext() 函數(shù)中 j 的初始化為 -1,但在 KMP() 函數(shù)中 j 的初始化為 0。

復(fù)雜度分析

代碼實(shí)現(xiàn)

暴力

class Solution {
public:
    vector<string> stringMatching(vector<string>& words) {
        // 新知識(shí):string::npos
        vector<string> ans;
        ans.clear();
        // 雙重循環(huán)暴力尋找
        for(auto &word1 : words){
            int l1 = word1.length();
            for(auto &word2 : words){
                int l2 = word2.length();
                // 當(dāng) l2 大于 l1 時(shí) 并且可以在 w2 中找到 w1 時(shí)
                if(l1 < l2 && word2.find(word1) != string::npos){
                    ans.emplace_back(word1);
                    break;
                }
            }
        }
        return ans;
    }
};

暴力 + 優(yōu)化

class Solution {
public:
    vector<string> stringMatching(vector<string>& words) {
        sort(words.begin(), words.end(), [](string &a, string &b){
            return a.length() < b.length();
        });
        // 新知識(shí):string::npos
        vector<string> ans;
        ans.clear();
        int n = words.size();
        // 雙重循環(huán)暴力尋找
        for(int i = 0; i < n; i++){
            int l1 = words[i].length();
            for(int j = i + 1; j < n; j++){
                int l2 = words[j].length();
                // 當(dāng) l2 大于 l1 時(shí) 并且可以在 w2 中找到 w1 時(shí)
                if(l1 < l2 && words[j].find(words[i]) != string::npos){
                    ans.emplace_back(words[i]);
                    break;
                }
            }
        }
        return ans;
    }
};

KMP

class Solution {
    void getNext(string &p, vector<int> &nxt){
        // 把PMT進(jìn)行向右偏移時(shí),第0位的值,我們將其設(shè)成了-1,
        // 這只是為了編程的方便,并沒有其他的意義。
        nxt[0] = -1;
        int i = 0, j = -1;
        int len = p.length();
        // ★注意 nxt 數(shù)組越界
        while(i < len){
            // j = -1 或者 匹配成功
            if(j == -1 || p[i] == p[j]){
                // nxt[++i] = ++j; 未優(yōu)化前
                i++;
                j++;
                if(p[i] == p[j]) nxt[i] = nxt[j];
                else nxt[i] = j;
            }
            // 匹配失敗,回溯
            else{
                j = nxt[j];
            }
        }
    }
    bool kmp(string &t, string &p, vector<int> &nxt){
        // ★注意這里的 j = 0 不是 j = -1
        int i = 0, j = 0;
        int lent = t.length();
        int lenp = p.length();
        while(i < lent && j < lenp){
            if(j == -1 || t[i] == p[j]){
                ++i;
                ++j;
            }
            else j = nxt[j];
        }
        if(j == lenp) return true;
        return false;
    }
public:
    vector<string> stringMatching(vector<string>& words) {
        sort(words.begin(), words.end(), [](string a, string b){
            return a.length() < b.length();
        });
        vector<string> ans;
        ans.clear();
        vector<int> nxt;
        int n = words.size();
        for(int i = 0; i < n; i++){
            int len_p = words[i].length();
            // ★注意 nxt 數(shù)組溢出
            // 可以這里 len_p + 1 也可以 getNext 中 -1
            nxt.resize(len_p + 1);
            getNext(words[i], nxt);
            for(int j = i + 1; j < n; j++){
                if(kmp(words[j], words[i], nxt)){
                    ans.emplace_back(words[i]);
                    break;
                }
            }
        }
        return ans;
    }
};

總結(jié)

  • 通過該題了解到了一個(gè)新的知識(shí)點(diǎn):string::npos 參數(shù)用來表示不存在的位置。當(dāng) stringfind() 函數(shù)沒有匹配成功時(shí),那么就會(huì)返回這個(gè)參數(shù) string::npos
  • 同時(shí)通過該題復(fù)習(xí)了 KMP 字符串匹配算法 的實(shí)現(xiàn),在實(shí)現(xiàn)過程中需要注意 nxt 數(shù)組的大小,防止下標(biāo)越界的運(yùn)行錯(cuò)誤;同時(shí)還需要注意在 getNext() 函數(shù)中 j 的初始化為 -1,但在 KMP() 函數(shù)中 j 的初始化為 0。

測(cè)試結(jié)果:

以上就是C C++算法題解LeetCode1408數(shù)組中的字符串匹配的詳細(xì)內(nèi)容,更多關(guān)于C C++算法數(shù)組字符串匹配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++詳細(xì)講解圖論的基礎(chǔ)與圖的儲(chǔ)存

    C++詳細(xì)講解圖論的基礎(chǔ)與圖的儲(chǔ)存

    圖論〔Graph?Theory〕是數(shù)學(xué)的一個(gè)分支。它以圖為研究對(duì)象。圖論中的圖是由若干給定的點(diǎn)及連接兩點(diǎn)的線所構(gòu)成的圖形,這種圖形通常用來描述某些事物之間的某種特定關(guān)系,用點(diǎn)代表事物,用連接兩點(diǎn)的線表示相應(yīng)兩個(gè)事物間具有這種關(guān)系
    2022-05-05
  • 簡(jiǎn)單談?wù)凜++ 中指針與引用

    簡(jiǎn)單談?wù)凜++ 中指針與引用

    下面用通俗易懂的話來概述一下,指針-對(duì)于一個(gè)類型T,T*就是指向T的指針類型,也即一個(gè)T*類型的變量能夠保存一個(gè)T對(duì)象的地址,而類型T是可以加一些限定詞的,引用-引用是一個(gè)對(duì)象的別名,主要用于函數(shù)參數(shù)和返回值類型,符號(hào)X&表示X類型的引用。
    2015-09-09
  • C語言 深入探究動(dòng)態(tài)規(guī)劃之區(qū)間DP

    C語言 深入探究動(dòng)態(tài)規(guī)劃之區(qū)間DP

    這幾天在做有關(guān)dp的題,看到一個(gè)石子合并的問題,本來以為是個(gè)貪心,后來仔細(xì)一想壓根不是貪心。貪心算法的思路是每次都取最大的,然而石子合并問題有個(gè)限制條件就是每次只能取相鄰的,這就決定了它不是個(gè)貪心
    2022-04-04
  • C++20中的協(xié)程(Coroutine)的實(shí)現(xiàn)

    C++20中的協(xié)程(Coroutine)的實(shí)現(xiàn)

    這篇文章主要介紹了C++20中的協(xié)程(Coroutine)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 深入理解strcpy與memcpy的區(qū)別

    深入理解strcpy與memcpy的區(qū)別

    本篇文章是對(duì)strcpy與memcpy的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Android App仿微信界面切換時(shí)Tab圖標(biāo)變色效果的制作方法

    Android App仿微信界面切換時(shí)Tab圖標(biāo)變色效果的制作方法

    這篇文章主要介紹了Android App仿微信界面切換時(shí)Tab圖標(biāo)變色效果的制作方法,重點(diǎn)講解了圖標(biāo)的繪制技巧,需要的朋友可以參考下
    2016-04-04
  • C++中友元的實(shí)例詳解

    C++中友元的實(shí)例詳解

    這篇文章主要介紹了C++中友元的實(shí)例詳解的相關(guān)資料,希望通過本文大家能掌握友元的使用方法,需要的朋友可以參考下
    2017-09-09
  • Arduino控制舵機(jī)詳解 附代碼

    Arduino控制舵機(jī)詳解 附代碼

    rduino是一款便捷靈活、方便上手的開源電子原型平臺(tái),它構(gòu)建于開放原始碼simple I/O介面版,并且具有使用類似Java、C語言的Processing/Wiring開發(fā)環(huán)境,這篇文章主要介紹了Arduino控制舵機(jī)詳解(含代碼),需要的朋友可以參考下
    2023-05-05
  • C++構(gòu)造函數(shù)+復(fù)制構(gòu)造函數(shù)+重載等號(hào)運(yùn)算符調(diào)用

    C++構(gòu)造函數(shù)+復(fù)制構(gòu)造函數(shù)+重載等號(hào)運(yùn)算符調(diào)用

    這篇文章主要介紹了C++構(gòu)造函數(shù)+復(fù)制構(gòu)造函數(shù)+重載等號(hào)運(yùn)算符調(diào)用,文章敘述詳細(xì),具有一定的的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • Qt之簡(jiǎn)單的異步操作實(shí)現(xiàn)方法

    Qt之簡(jiǎn)單的異步操作實(shí)現(xiàn)方法

    這篇文章主要介紹了Qt之簡(jiǎn)單的異步操作實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評(píng)論

全州县| 迁安市| 嘉义县| 柳江县| 左贡县| 浠水县| 乌拉特后旗| 新宁县| 龙江县| 简阳市| 罗平县| 万荣县| 六盘水市| 美姑县| 永康市| 康乐县| 利津县| 涿州市| 建始县| 潜江市| 英吉沙县| 乐山市| 吴桥县| 蕉岭县| 南溪县| 镇宁| 库伦旗| 龙泉市| 江陵县| 桑植县| 西吉县| 万全县| 芒康县| 南川市| 赤壁市| 崇阳县| 长乐市| 东台市| 二连浩特市| 红原县| 靖宇县|