问题:“由各种字母组成的字符串S,另外一个字母数相对少一些的字符串T,设法最快的查出是否T中的字母均在S中?”
思路:
判断集合A是否包含集合B,即判断其差(A-B)是否为空集。(A-B)不好算,可换为求(A -(A交B))。
考虑集合的表示方面,没要求顺序,即无序集。
仅考虑26个小写字母的情况,自然地想用位向量。用32位整数表示集合,第0位为1表示含'a',第1位为1表示含'b',……
#include <cassert> #include <iostream> using namespace std; /* 这个示意性的程序仅考虑了26个小写字母。 若字符集更大可换用数组作为字符串的“签名”,对UNICODE,0x10FFFF个字符用int[]不过4M内存,也可继续按位存储省点内存。 */ int str_sig(char const *ps) { assert(ps); assert(isalpha(*ps)); int sig = 0; while(*ps){ sig |= (1 << (*ps - 'a')); ++ps; } return sig; } bool contains_charset(char const *psa, char const *psb) { int sig_a = str_sig(psa); int sig_b = str_sig(psb); return ((sig_a & sig_b) ^ sig_b) == 0; } void test(char const *psa, char const *psb) { cout << "\"" << psa << "\" " << (contains_charset(psa, psb) ? "" : "not ") << " contains \"" << psb << "\"\n"; } int main() { assert(str_sig("") == 0); assert(str_sig("a") == (1 << 0)); assert(str_sig("z") == (1 << 25)); assert(str_sig("abcdefghijklmnopqrstuvwxyz") == ((1 << 26) - 1)); test("", ""); test("a", "a"); test("a", "b"); test("ab", "b"); test("bc", "b"); test("abc", "b"); test("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); return 0; }