面试题6:字符串的包含
2016-03-21 20:47 Keiven_LY 阅读(454) 评论(0) 编辑 收藏 举报题目描述
给定一长字符串a和一短字符串b,请问,如何最快判断出b中的所有字符是否都在a中?请编写函数bool StringCOntain(string &a, string &b)实现此功能。
举例:
- 如果字符串a是”ABCD”,字符串b是”BAD”,则返回true,因为字符串b中的所有字符都在字符串a中,或者说b是a的子集。
- 如果字符串a是”ABCD”,字符串b是”BCE”,则返回false,因为字符串b中的字符E不在字符串a中
- 如果字符串a是”ABCD”,字符串b是”AA”,则返回true,因为字符串b中的字母A包含在字符串a中。
方法一:蛮力轮询
基本思想:轮询b中所有字符,逐个与字符串a中的每一个字符进行比较,看是否都在字符串a中。
bool StringContain(string &a, string &b) { for(int i=0;i<b.length();i++) { for(int j=0;(j<a.length()) && (a[j] != b[i]);j++) ; if(j>=a.length()) { return false; } } return true; }
注解:如果字符串a的长度为m,字符串b的长度为n,则该算法的时间复杂度就是O(mn),显然,当m,n较大时,该算法的时间开销会很大。
方法二:素数相乘
基本思想:
首先,让字符串a中的每个字符对应一个素数,如A对应2,B对应3,C对应5,……以此类推。然后将a中的每个字符对应的素数相乘,得到一个整数。然后,让字符串b中的每一个字符也对应相应的素数,再用b中的每个字符对应的素数除上面得到的整数。如果有余数,说明结果为false,立即退出程序;如果整个过程中没有余数,则说明b是a的子集。
bool StringContain(string &a, string &b) { const int p[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 result=1;//存放字符串a每个字符对应素数的乘积 for(int i=0; i<a.length(); i++) { int x = p[a[i] - 'A']; if(result % x) { result *= x; } } for(int i=0; i<b.length(); i++) { int x=p[b[i] - 'A']; if(resuilt % x) return false; } return true; }
分析:算法的时间复杂度是O(m+n),最好情况下的时间复杂度是O(m),即在遍历b的第一个字符,就产生余数,便直接退出程序。
这种素数相乘看似可行,实则不行。因为素数相乘的结果可能会非常大,从而导致整数溢出。(前16个字母对应的素数相乘便会超出long long类型所能表示的最大整数范围)。