題目描述:假設這有一個各種字母組成的字符串A,和另外一個字符串B,字符串裏B的字母數相對少一些。什麼方法能最快的查出所有小字符串B裏的字母在大字符串A裏都有?原文連接:http://blog.csdn.net/v_july_v/article/details/6347454
比如,如果是下面兩個字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPO
答案是true,所有在string2裏的字母string1也都有。
如果是下面兩個字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPZ
答案是false,因爲第二個字符串裏的Z字母不在第一個字符串裏。
思路1:最先想到的是循環逐個比較字符,外循環水短字符串,內循環是長字符串,判斷短字符串中字符在長字符串中是否存在。
時間複雜度O(n*m)
bool StringCompare(string shortStr,string longStr)
{
for(int i=0;i<shortStr.length();i++)
{
for(int j=0;j<longStr.length();j++)
{
if(longStr[j]==shortStr[j])
{
break;
}
}
if(j==longStr.length())
{
return false;
}
}
return true;
}
思路2:對2個字符串排序後再比較。排序時間複雜度+線性比較時間複雜度O(m+n)。關鍵在於排序的時間複雜度了。
排序可以有多種方式,這裏選擇2中。
排序1:快速排序,時間複雜度O(nlog n)+O(mlog m)
int Partation(string &str,int begin,int end)
{
char key =str[end];
int index=begin-1;
for (int i=begin;i<end;i++)
{
if(str[i]<key)
{
index++;
if(index!=i)
{
swap(str[index],str[i]);
}
}
}
if((index+1)!=end)
{
swap(str[index+1],str[end]);
}
return index+1;
}
void StringSort::QuickSort(string & str,int begin,int end)
{
if(begin<end)
{
int index=Partation(str,begin,end);
QuickSort(str,begin,index-1);
QuickSort(str,index+1,end);
}
}
排序2:計數排序,利用hasetable 或者 int數組,類似桶排序,時間複雜度O(m+n)。下面是利用數組的實現:
void StringSort::CountSort(string & str)
{
int a[26]={0};
for(int i=0;i<str.length();i++)
{
int index=str[i]-'A';
a[index]++;
}
//求每個字符的位置
for (int j=1;j<26;j++)
{
a[j]+=a[j-1];
}
string str2=str;
for (int k=0;k<str2.length();k++)
{
int s=str2[k]-'A';
int pos=a[s]-1;
str[pos]=str2[k];
a[s]--;
}
}
思路3:同思路2類似,利用int數組或者hasetable,但不排序,利用bool標記,先把短字符放進容器,值爲1。然後遍歷場長字符,容器中有的值就改爲0。最後根據容器中是否還有值爲1來判斷是否包含。時間複雜度O(m+n)
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1="ABCDEFGHLMNOPQRS";
string str2="DCGSRQPOM";
// 開闢一個輔助數組並清零
int hash[26] = {0};
// num爲輔助數組中元素個數
int num = 0;
// 掃描短字符串
for (int j = 0; j < str2.length(); j++)
{
// 將字符轉換成對應輔助數組中的索引
int index = str1[j] - 'A';
// 如果輔助數組中該索引對應元素爲0,則置1,且num++;
if (hash[index] == 0)
{
hash[index] = 1;
num++;
}
}
// 掃描長字符串
for (int k = 0; k < str1.length(); k++)
{
int index = str1[k] - 'A';
// 如果輔助數組中該索引對應元素爲1,則num--;爲零的話,不作處理(不寫語句)。
if(hash[index] ==1)
{
hash[index] = 0;
num--;
if(num == 0) //m==0,即退出循環。
break;
}
}
// num爲0說明長字符串包含短字符串內所有字符
if (num == 0)
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}
思路4:素數,爲每個字符分配一個素數,先求長字符素數相乘的積,然後逐個除短字符對於的素數,如果不恩整除,說明不包含。時間複雜度爲0(m+n)引用原作者的代碼實現
#include <iostream>
#include <string>
#include "BigInt.h"
using namespace std;
// 素數數組
int primeNumber[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, 97, 101};
int main()
{
string strOne = "ABCDEFGHLMNOPQRS";
string strTwo = "DCGSRQPOM";
// 這裏需要用到大整數
CBigInt product = 1; //大整數除法的代碼,下頭給出。
// 遍歷長字符串,得到每個字符對應素數的乘積
for (int i = 0; i < strOne.length(); i++)
{
int index = strOne[i] - 'A';
product = product * primeNumber[index];
}
// 遍歷短字符串
for (int j = 0; j < strTwo.length(); j++)
{
int index = strTwo[j] - 'A';
// 如果餘數不爲0,說明不包括短字串中的字符,跳出循環
if (product % primeNumber[index] != 0)
break;
}
// 如果積能整除短字符串中所有字符則輸出"true",否則輸出"false"。
if (strTwo.length() == j)
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}