题目:
给定一个长字符串a,和一个短字符串b,如何最快的判断出短字符串b中的所有字符是否都在长字符串a中?
方法一:暴力轮询。
方法二:先排序后再轮询。
代码:
#include <bits/stdc++.h>
using namespace std;
bool StringContain(string &a,string &b){
sort(a.begin(),a.end());
sort(b.begin(),b.end());
int pa=0,pb=0;
while(pb < b.length()){
//直到找到a[pa] == a[pb],否自pa一直前移
while((pa < a.length()) && (a[pa] < a[pb])){
++pa;
}
//判出,pa越界 或 找到了后面的大于a[pa]的值,证明不满足条件
if((pa >= a.length()) || (a[pa] > a[pb])){
return false;
}
++pb;
}
return true;
}
int main(){
string s1="abcd";
string s2="bcd";
if(StringContain(s1,s2)){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
return 0;
}
方法三:素数相乘
这是一种解答思路:将26个字符中的每个字符和一个素数相对应,然后算出长字符串a中字符对应的素数的积pro;
然后做 pro / 短字符串b中每个字符对应的素数,如果有余数说明1,个数不达标,2,a中没有出现该字符
注:因为字符串可能很长,所以有可能会溢出,短的可以长的不行。
#include <bits/stdc++.h>
using namespace std;
bool StringContain2(string &a,string &b){
const int pri[26]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,
53,59,61,71,73,79,83,89,97,101};
int pro=1;//a的素数的积
for(int i=0;i<a.length();++i){
int x=pri[a[i] - 'a'];//对应的素数
if(pro % x){//省去个数
pro*=x;
}
}
for(int j=0;j<b.length();++j){
int y=pri[b[j]-'a'];
if(pro % y){
return false;
}
}
return true;
}
int main(){
string s1="abcd";
string s2="bcd";
if(StringContain2(s1,s2)){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
return 0;
}
方法四:位运算法
更简单的方法是将a中的字符放入散列表中,然后再轮询比较b中的字符,这里可以用位运算为a算出一个 定值
然后再将b中的字符逐一放到a中去查找。
#include <bits/stdc++.h>
using namespace std;
//实质是用一个整数代替了散列表
bool StringContain3(string &a,string &b){
int hash=0;
for(int i=0;i<a.length();++i){
hash |= (1<<(a[i]-'a'));
}
for(int i=0;i<b.length();++i){
if((hash & (1<<(b[i]-'a')))==0){
return false;
}
}
return true;
}
int main(){
string s1="abcd";
string s2="bcd";
if(StringContain3(s1,s2)){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
return 0;
}