字串的包含問題簡單情況下的幾個演算法
阿新 • • 發佈:2018-12-01
《程式設計之法》Page5的問題
題目描述:給定一個長字串a和段字串b,a、b均不為空。請問,如何才能最快地判斷出短字串b中的所有字元是否在長串a中?編寫bool StringContain(string &a,string &b)函式實現此功能。
書上列舉了4中方法(書中還提到一種排序計數的方法),時間複雜度逐漸減小。這些方法分別是:(1)蠻力輪詢(2)排序後輪詢(3)素數相乘(4)位運演算法
前面3種演算法設計起來都沒什麼難度,下面我貼出我認為比較難想到的位運演算法程式碼:
正如註釋寫的一樣,這種方法很巧妙地用位運算子降低了求解難度……時間複雜度也較低。/* 對於只含26位大寫字母的字串A,我們可以只使用一個int型變數hash作為hash表,這是因為int變數有32bit。 若字串A中含有字元A,則令變數hash的第1位置1,若字串A中含有y,則令變數hash的第25位置1。 對於字串B中任一字元,只需判斷該字元在變數hash中所對應的位是否為1。 這樣時間複雜度為O(m+n),空間複雜度為O(1)。 */ #include <bitset> #include <iostream> #include <algorithm> #include <string> using namespace std; bool StringContain(string &a,string &b); void BinaryBitset(int n) { cout<<bitset<sizeof(int)*8>(n)<<endl; } void alphaPrint(){ char alpha[26]; cout<<"000000"; for(int i = 0; i < 26; i++) { alpha[i] = 'Z' - i; cout<<alpha[i]; } cout<<endl; } int main() { string a = "AKSJLKDPMN"; string b = "AKAB"; cout<<StringContain(a,b)<<endl; return 0; } bool StringContain(string &a,string &b) { int hash = 0; for( int i = 0; i < a.length(); ++i) { hash |= (1 << (a[i]-'A') ); //hash = hash | ( 1 << (a[i]-'A') ) hash或上1左移a[i]-'A'位,用0補位 } cout<<"hash用2進製表示為:(對應的字元在下方 & 1 == true)\n"; BinaryBitset(hash); alphaPrint(); for(int i = 0; i < b.length(); ++i) { if((hash & (1 << (b[i]-'A'))) == 0) return false; } return true; }
就我個人而言,頂多想到這種方法:(1)將a中元素排序;(2)遍歷b中元素,利用二分查詢,尋找每個b中元素是否存在於a中
下午我實現了我個人的演算法,原始碼如下:
程式碼不是很難,但是我寫了一下午……//將a串排序之後,用b中的字元依次二分查詢 #include <string> #include <iostream> #include <algorithm> using namespace std; bool StringContain(string &a,string &b); int BSearch(char x, string &a, int begin, int end); int main() { string a = "AKSJLKDJACBLSBJLAS"; string b = "ACE"; cout<<StringContain(a,b)<<endl; system("PAUSE"); return 0; } bool StringContain(string &a,string &b) { sort(a.begin(),a.end()); //將a、b串預先排序 int aLength = a.size(); int bLength = b.size(); int result = -1; for(int i = 0; i < bLength; i++) { result = BSearch(b[i],a,0,aLength); if( result >= 0 && result <= aLength ) continue; else return false; } return true; } int BSearch(char x, string &a, int begin, int end) { if( begin >= end) return -1; int median = (begin+end)/2; char y = a[median]; if( x == y ) return median; else if( x > y ) return BSearch(x,a,median+1,end); else return BSearch(x,a,begin,median); }
看來還是太嫩了