挑战面试编程:字符串包含

来源:互联网 发布:openstack linux 编辑:程序博客网 时间:2024/05/21 09:15

                        挑战面试编程:字符串包含

    字符串查找是在一个大的文本中查找一个给定的模式串,常用的算法有KMP、BM、Sunday等。而字符串包含要求比较低:只要字符包含就行,不需要模式串作为整体出现。

例如,S="abcd",T="ac",做查找运算,则T不在S中;做包含运算,T包含在S中。


方法一
最简单的就是对T中的每一个字符都在S中进行查找,都存在,则包含。

/*字符串包含--朴素法判断字符串T中的字符是否全都在字符串S中*/bool contains(char *S, char *T){assert(S && T);int SLen, TLen;SLen = strlen(S), TLen = strlen(T);int i, j;i = 0, j = 0;while (j < TLen){i = 0;while (i < SLen){if (T[j] == S[i])break;i++;}if (i == SLen)return false;j++;}return true;}
在最坏的情况下,对于T中的每一个字符都遍历一遍S,则时间复杂度是O(mn)


方法二

先对对两个字符串排序,排序后再检索,这样的检索效率高。

/*字符串包含--排序比较法判断字符串T中的字符是否全都在字符串S中*/bool contains2(char *S, char *T){assert(S && T);int SLen, TLen;SLen = strlen(S), TLen = strlen(T);/*先排序sort(first, last)函数对[first, last)范围的数据按升序排序*/sort(S, S + SLen);sort(T, T + TLen);//puts(S);//puts(T);int i, j;i = 0, j = 0;while (j < TLen){while (i < SLen && S[i] < T[j])i++;if (i == SLen || S[i] > T[j])return false;j++;}return true;}
S的长度是n,T的长度是m,则排序是O(nlogn+mlogm),检索是O(m+n),时间复杂度是O(nlogn+mlogm+m+n)。排序可采用更高效的计数排序。

方法三

素数法,利用素数特有的性质:除1和本身外再无其它因数。

/*字符串包含--素数法判断字符串T中的字符是否全都在字符串S中*/bool contains3(char *S, char *T){assert(S && T);int SLen, TLen;SLen = strlen(S), TLen = strlen(T);int prime[26] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 91, 97 };long long mul = 1;int i, x;for (i = 0; i < SLen; i++){x = prime[S[i] - 'a'];//为了防止mul过大,去掉重复的素数if (mul % x)mul *= x;}for (i = 0; i < TLen; i++)if (mul % prime[T[i] - 'a'])return false;return true;}
最好O(n),在遍历T的第一个字符时就失败。最坏O(n+m),需要遍历完T。素数法并不完美,素数相乘的乘积可能过大,造成溢出。故效率高,但不推荐使用。


方法四

对两字符串构造位图,然后进行集合的包含运算判断。

/*字符串包含--位图法判断字符串T中的字符是否全都在字符串S中*/bool contains4(char *S, char *T){assert(S && T);bitset<26> s, t;int SLen, TLen;SLen = strlen(S), TLen = strlen(T);s.reset();t.reset();int i;for (i = 0; i < SLen; i++)s.set(S[i] - 'a');for (i = 0; i < TLen; i++)t.set(T[i] - 'a');//若S包含T,则集合s包含t//或者return (s.to_ulong() & t.to_ulong()) == t.to_ulong();    return (s.to_ulong() | t.to_ulong()) == s.to_ulong();}
时间复杂度显然是O(m+n)。


方法五

这是位运算法,也叫哈希法,它与位图法本质上是一样的。

/*字符串包含--位运算法判断字符串T中的字符是否全都在字符串S中*/bool contains5(char *S, char *T){assert(S && T);int SLen, TLen;SLen = strlen(S), TLen = strlen(T);int i, bit;bit = 0;for (i = 0; i < SLen; i++)bit |= (1 << (S[i] - 'a'));for (i = 0; i < TLen; i++)if ((bit & (1 << (T[i] - 'a'))) == 0)return false;return true;}


所有内容的目录

  • CCPP Blog 目录

1 1