字符串包含
2016-07-27 18:39
155 查看
问题描述:
给定长字符串a和一短字符串b,如何判断出短字符串b中的所有字符是否都在长字符串a中?说明,重复的字母算同一个
解法一 蛮力轮询
对于字符串b中的每一个字母,依次逐个与字符串a中的每个字符进行比较,看是否都在字符串a中。
若两个字符串的长度为n,m,则该解法的时间复杂度为O(m*n)
#include <iostream>
using namespace std;
bool StringContain(string A,string B){
for(int i=0;i<B.length();i++){
int j = 0;
for(j=0;(j<A.length()&&A[j]!=B[i]);j++);
if(j >= A.length())
return false;
}
return true;
}
int main(){
string strA,strB;
cin>>strA;
cin>>strB;
if(StringContain(strA,strB))
cout<<"YES"<<endl; //表示A包含B
else
cout<<"NO"<<endl;
return 0;
}
解法二 先排序 后轮询
大致意思是 先将两个字符串里的字母按照ASCII 的顺序排好,然后并行地线性扫描即可。
时间复杂度 O(mlgm) + O(nlgn) + O(m+n) , 很明显,这种方法优于上一种暴力算法
解法三 素数相乘
大致意思是,将字符串a里的每一个字母按序用一个素数来表示,然后将每个字母代表的素数相乘,分别除以字符串b里面每个字符代表的素数,若发现有余数,则表示出现了新的元素,即不包含。
可以这样做的理由是,素数的特性,只能被1和它自身整除,所以元素之间就保证了互异性。也就是说,只有b里面的字母是包含在a内的,才会整除。否则肯定是有余数的。
但是这样做的不利之处是,如果字符串长度过大,乘积的结果会出现溢出。
解法四 位运算法
这是一种极好的方法。空间复杂度为O(1),时间复杂度为O(m+n)
思想是,用位运算为字符串构造一个唯一的序列,然后只要逐一将字符串b中的字符与序列进行&运算即可。
比如,ABCD表示的序列是1111,ADF表示的序列是100101,……对于每一个字符只要将其左移一定的位数,位数的值等于ASCII码与A的ASCII码的差值
#include <iostream>
using namespace std;
bool StringContain(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 strA,strB;
cin>>strA;
cin>>strB;
if(StringContain(strA,strB))
cout<<"YES"<<endl; //表示A包含B
else
cout<<"NO"<<endl;
return 0;
}
给定长字符串a和一短字符串b,如何判断出短字符串b中的所有字符是否都在长字符串a中?说明,重复的字母算同一个
解法一 蛮力轮询
对于字符串b中的每一个字母,依次逐个与字符串a中的每个字符进行比较,看是否都在字符串a中。
若两个字符串的长度为n,m,则该解法的时间复杂度为O(m*n)
#include <iostream>
using namespace std;
bool StringContain(string A,string B){
for(int i=0;i<B.length();i++){
int j = 0;
for(j=0;(j<A.length()&&A[j]!=B[i]);j++);
if(j >= A.length())
return false;
}
return true;
}
int main(){
string strA,strB;
cin>>strA;
cin>>strB;
if(StringContain(strA,strB))
cout<<"YES"<<endl; //表示A包含B
else
cout<<"NO"<<endl;
return 0;
}
解法二 先排序 后轮询
大致意思是 先将两个字符串里的字母按照ASCII 的顺序排好,然后并行地线性扫描即可。
时间复杂度 O(mlgm) + O(nlgn) + O(m+n) , 很明显,这种方法优于上一种暴力算法
解法三 素数相乘
大致意思是,将字符串a里的每一个字母按序用一个素数来表示,然后将每个字母代表的素数相乘,分别除以字符串b里面每个字符代表的素数,若发现有余数,则表示出现了新的元素,即不包含。
可以这样做的理由是,素数的特性,只能被1和它自身整除,所以元素之间就保证了互异性。也就是说,只有b里面的字母是包含在a内的,才会整除。否则肯定是有余数的。
但是这样做的不利之处是,如果字符串长度过大,乘积的结果会出现溢出。
解法四 位运算法
这是一种极好的方法。空间复杂度为O(1),时间复杂度为O(m+n)
思想是,用位运算为字符串构造一个唯一的序列,然后只要逐一将字符串b中的字符与序列进行&运算即可。
比如,ABCD表示的序列是1111,ADF表示的序列是100101,……对于每一个字符只要将其左移一定的位数,位数的值等于ASCII码与A的ASCII码的差值
#include <iostream>
using namespace std;
bool StringContain(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 strA,strB;
cin>>strA;
cin>>strB;
if(StringContain(strA,strB))
cout<<"YES"<<endl; //表示A包含B
else
cout<<"NO"<<endl;
return 0;
}
相关文章推荐
- Xargs用法详解
- web前台后台实现下载功能
- POJ 1067 wythoff博弈
- 银联的跨行清算体系架构分析
- HttpURLConnection 上传图片(文件)到服务器
- MYSQL常用架构与调优经验分享
- Mybatis二级缓存应用场景和局限性
- ping 原理与ICMP协议
- 开发日记——手机安全卫士 Day08 2016-7-27 完成软件管家功能
- java 提取曲线图数值并导出excel
- Centos 下安装 Nginx
- gitconfig中磨刀不误砍柴工的小配置
- cornerstone上传静态库.a
- string与wstring之间的转换
- Ubuntu 14.04 LTS 实现双机文件同步lsync和rsync
- Java同步队列(非阻塞队列与阻塞队列)——java并发容器
- 渐渐明白习以为常的珍贵
- POJ1830 开关问题【 高斯消元】
- Java数组的几种常用操作方法(排序算法及查找)
- 【RabbitMQ 参考资料】