字符串的包含问题简单情况下的几个算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wang_926498/article/details/51985374

《编程之法》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);
}
代码不是很难,但是我写了一下午……

看来还是太嫩了尴尬尴尬尴尬


猜你喜欢

转载自blog.csdn.net/Wang_926498/article/details/51985374