编程艺术之第二章:字符串包含
来源:互联网 发布:matlab智能算法工具箱 编辑:程序博客网 时间:2024/05/01 19:40
题目描述:有一个较长的字符串A和较短的字符串B,如何快速查找是否A全部包含B,即B字符串里的字符A中都有。注意:不用顺序一致,只要包含即可。
如:StringA:ABCDEFGHLMNOPQRS
StringB:DCGSRQPO
则返回true。
思路1:
看到这题,我的第一反应就是逐个比较(毕竟我的经验不多,想法比较单纯~~~)。获取A和B两个字符串的长度,假设B较短,则把B中的字符一个个提取出来与A中的进行比较。如果length(A) = m,length(B) = n,且m>n,则最坏情况下时间复杂度是O(n*m)。这样的方法效率比较低,想想有木有改善的地方?
思路1的代码如下:
#include <iostream>#include <stdio.h>using namespace std;bool compare_chars(char* str1,char* str2);int get_char_length(char* str);int main(){char A[] = "ABCDEFGHLMNOPQRS";char B[] = "DCGSRQPOZ";printf("A的长度是%d\nB的长度是%d\n",get_char_length(A),get_char_length(B));bool isCompare = compare_chars(A,B);if(isCompare)printf("包含");elseprintf("不包含");getchar();return 0;}int get_char_length(char* str){if(str == NULL)return -1;else{int length = 0;while (str[length++] != '\0');return length-1;}}//思路1bool compare_chars(char* str1,char* str2){char temp;const int length_A = get_char_length(str1);const int length_B = get_char_length(str2);for (int i = 0 ;i < length_B;i++){temp = *(str2+i);int j = 0;while(temp != *(str1 + j) && j < length_A)j++;if(length_A == j)return false;}return true;}
思路2:
可以先把两个字符串进行排序,好的排序算法可以降低时间复杂度,而排序完成之后就可以对两个字符串进行轮询扫描。假设两个字符串是从小到大进行排序的,再进行扫描时,先建立两个指针分别指向两个字符串的起点(pA,pB)
如果*(pA) < *(pB) 则pB不动,pA++向后移动
如果*(pB) < *(pA) 则pA不动,pB++向后移动
如果B字符串中有一个字符是未在A中发现与其相等的字符(即*(pA) < *(pB)时,pA++,然后*(pA) > *(pB),此时表示pB未等于过,所以pB查找失败),B字符串后续的字符也不用进行查询了。
最坏情况下是O(m+n)的时间复杂度。
加上排序所消耗的时间复杂度,总体时间复杂度 应该是O(mlongm)+O(nlogn)+O(m+n)
思路2的代码如下:
//思路2void quick_sort(char*str,int left,int right){char f,t;int rtemp,ltemp;rtemp = right;ltemp = left;f = *(str + (left + right)/2);while(ltemp < rtemp){while(*(str + ltemp) < f)++ltemp;while(*(str + rtemp) > f)--rtemp;if (ltemp < rtemp){t = *(str+ltemp);*(str+ltemp) = *(str+rtemp);*(str+rtemp) = t;++ltemp;--rtemp;}}if (ltemp == rtemp){ltemp++;}if (left < rtemp){quick_sort(str,left,ltemp-1);}if (right > ltemp){quick_sort(str,rtemp+1,right);}}bool compare_chars(char* str1,char* str2){//1 先进行排序---快速排序const int length_A = get_char_length(str1);const int length_B = get_char_length(str2);quick_sort(str1,0,length_A-1);quick_sort(str2,0,length_B-1);//2 轮询比较int i = 0, j = 0;while(i<length_A && j < length_B){if(*(str1+i) < *(str2+j))i++;else if(*(str1+i) == *(str2+j)){if (i == length_A - 1 && j == length_B - 1)return true;else{j++;i++;}}elsereturn false;}if (str1[i] == '\0')return false;return true;}
思路3:
既然思路2的时间复杂度是O(mlogm)+O(nlogn)+O(m+n),那么有没有可能将时间复杂度极限成O(m+n)?是不是可以使用第三方存储空间?有些算法不允许使用。所以我就在想,既然是大写英文字符,那么最多就是26个,如果先把B字符串里的字符全部记录下来,再让A来比较就好了,只不过这需要中间的一个桥梁,毕竟进行B标记的与A比较的应该相同。所以可以构建一个数组,长度为26(26是个关键长度)。
初始化:int position[26] = {0};
针对B字符串的对应的26个英文字母的序号填充position数组,若出现,则将值置为1,否则保持0,最后记录长度为m。
序列完B之后,将A的字符也进行比较,如果也出现同样的字符,则将1置为0,同时m-1,如果未出现,则保持不变。
最后检测m的长度是否为0,如果不为0,说明false,反正为true.
这就实现了对每个字符串里的字符只访问一次。
思路3的代码如下:
后来发现这就是hashtable的想法啊,= =!!!-。-
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
思路4 的代码如下:
#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; }
- 编程艺术之第二章:字符串包含
- 程序员编程艺术:第二章、字符串是否包含问题
- 程序员编程艺术:第二章、字符串是否包含问题
- 读程序员编程艺术第二章---字符串包含问题
- 读程序员编程艺术第二章---字符串包含问题(二)
- 【程序员编程艺术】第二章:字符串是否包含问题
- 程序员编程艺术:第二章、字符串是否包含问题
- 程序员编程艺术:第二章、字符串是否包含问题
- 程序员编程艺术:第二章、字符串是否包含问题
- [整理]程序员编程艺术:第二章、字符串是否包含问题
- 编程艺术之1.2字符串包含_test1
- 程序员编程艺术:第二章、字符串是否包含及匹配/查找/转换/拷贝问题
- 程序员编程艺术:第二章、字符串是否包含及匹配/查找/转换/拷贝问题
- 程序员编程艺术:第二章、字符串是否包含及匹配/查找/转换/拷贝问题
- 程序员编程艺术:第二章、字符串是否包含及匹配/查找/转换/拷贝问题
- 个人解法 ------- 程序员编程艺术:第二章、字符串是否包含问题
- 程序员编程艺术:第二章、字符串是否包含及匹配/查找/转换/拷贝问题
- 【July程序员编程艺术】之字符串是否包含问题
- Linux USB Gadget--各环节的整合
- Java监听器用法(三):外部类监听器
- Lua 语言 15 分钟快速入门(转)
- makefile 常用函数notdir、wildcard、patsubst
- 幻方的实现,矩阵每行每列每个对角线之和相等
- 编程艺术之第二章:字符串包含
- Linux USB Gadget--设备枚举
- Remove Nth Node From End of List
- 图像处理中目标函数求解方法整理(更新一部分)
- UITabBarItem初始化详解及UIImage渲染模式
- 1052. Linked List Sorting (25)
- 日文游戏常见日语单词及读音
- ubuntu下X Windows下网络图标未出现以及后续的设备未托管问题解决方案。
- your project contains error(s),please fix them before running your application