演算法 字串包含

2021-07-03 13:34:13 字數 2570 閱讀 5633

給定兩個分別由字母組成的字串a和字串b,字串b的長度比字串a短。請問,如何最快地判斷字串b中所有字母是否都在字串a裡?

為了簡單起見,我們規定輸入的字串只包含大寫英文本母,請實現函式bool stringcontains(string &a, string &b)

比如,如果是下面兩個字串:

string 1:abcd

string 2:bad

答案是true,即string2裡的字母在string1裡也都有,或者說string2是string1的真子集。

如果是下面兩個字串:

string 1:abcd

string 2:bce

答案是false,因為字串string2裡的e字母不在字串string1裡。

同時,如果string1:abcd,string 2:aa,同樣返回true。

題目描述雖長,但題意很明了,就是給定一長一短的兩個字串a,b,假設a長b短,要求判斷b是否包含在字串a中。

初看似乎簡單,但實現起來並不輕鬆,且如果面試官步步緊逼,乙個乙個否決你能想到的方法,要你給出更好、最好的方案時,恐怕就要傷不少腦筋了。

判斷string2中的字元是否在string1中?最直觀也是最簡單的思路是,針對string2中每乙個字元,逐個與string1中每個字元比較,看它是否在string1中。

**可如下編寫:

bool

stringcontain(string &a,string &b)

}return

true;

}

假設n是字串string1的長度,m是字串string2的長度,那麼此演算法,需要o(n*m)次操作。顯然,時間開銷太大,應該找到一種更好的辦法。

如果允許排序的話,我們可以考慮下排序。比如可先對這兩個字串的字母進行排序,然後再同時對兩個字串依次輪詢。兩個字串的排序需要(常規情況)o(m log m) + o(n log n)次操作,之後的線性掃瞄需要o(m+n)次操作。

關於排序方法,可採用最常用的快速排序,參考**如下:

//注意a b中可能包含重複字元,所以注意a下標不要輕易移動。這種方法改變了字串。如不想改變請自己複製

bool

stringcontain(string &a,string &b)

if ((pa >= a.length()) || (a[pa] > b[pb]))

//a[pa] == b[pb]

++pb;

}return

true;

}

有沒有比快速排序更好的方法呢?

我們換一種角度思考本問題:

假設有乙個僅由字母組成字串,讓每個字母與乙個素數對應,從2開始,往後類推,a對應2,b對應3,c對應5,......。遍歷第乙個字串,把每個字母對應素數相乘。最終會得到乙個整數。

利用上面字母和素數的對應關係,對應第二個字串中的字母,然後輪詢,用每個字母對應的素數除前面得到的整數。如果結果有餘數,說明結果為false。如果整個過程中沒有餘數,則說明第二個字串是第乙個的子集了(判斷是不是真子集,可以比較兩個字串對應的素數乘積,若相等則不是真子集)。

思路總結如下:

按照從小到大的順序,用26個素數分別與字元'a'到'z'一一對應。

遍歷長字串,求得每個字元對應素數的乘積。

遍歷短字串,判斷乘積能否被短字串中的字元對應的素數整除。

輸出結果。

如前所述,演算法的時間複雜度為o(m+n)的最好的情況為o(n)(遍歷短的字串的第乙個數,與長字串素數的乘積相除,即出現餘數,便可退出程式,返回false),n為長字串的長度,空間複雜度為o(1)。

//此方法只有理論意義,因為整數乘積很大,有溢位風險

bool

stringcontain(string &a,string &b)

; int f = 1;

for (int i = 0; i < a.length(); ++i)

}for (int i = 0; i < b.length(); ++i)

}return

true;

}

此種素數相乘的方法看似完美,但缺點是素數相乘的結果容易導致整數溢位。

如果面試官繼續追問,還有沒有更好的辦法呢?計數排序?除了計數排序呢?

事實上,可以先把長字串a中的所有字元都放入乙個hashtable裡,然後輪詢短字串b,看短字串b的每個字元是否都在hashtable裡,如果都存在,說明長字串a包含短字串b,否則,說明不包含。

再進一步,我們可以對字串a,用位運算(26bit整數表示)計算出乙個「簽名」,再用b中的字元到a裡面進行查詢。

// 「最好的方法」,時間複雜度o(n + m),空間複雜度o(1)

bool

stringcontain(string &a,string &b)

for (int i = 0; i < b.length(); ++i)

}return

true;

}

這個方法的實質是用乙個整數代替了hashtable,空間複雜度為o(1),時間複雜度還是o(n + m)。

1、變位詞

字串包含演算法

題目如下 給定乙個長字串a和短字串b,如何判斷短字串b中所有字元的是否都在長字串a中?方法如下 1.簡單粗暴的方法 蠻力輪詢 不推薦 思路 遍歷字串b中的每乙個字元,判斷該字元是否在字串a中。時間複雜度 o nm 其中n為a的長度,m為b的長度 2.排序後輪詢 思路 先對字串a和字串b進行排序,然後...

字串包含問題演算法

現在假設有2個字串r和s,其中m r.len n s.len,設計乙個演算法判斷字串s中的每個字元在r串中均存在.顯然,很容易想到的乙個演算法,最粗魯最暴力演算法,其時間複雜度o m n 也就是對s字串中的每個字元在r中進行查詢判斷 這或許是我自己想到的最快的方法了。顯而易見,這樣的演算法或許不是演...

字串包含

問題 給定兩個分別由字母組成的字串a和字串b,字串b的長度比字串a短。請問,如何最快地判斷字串b中所有字母是否都在字串a裡?為了簡單起見,我們規定輸入的字串只包含大寫英文本母,請實現函式bool stringcontains string a,string b 比如,如果是下面兩個字串 string...