字符串是否包含问题

题目描述:
有两个字符串一个长字符串str1,一个短字符串str2,查找第二个字符串的所有字符是否第一个字符串里面都包含。
例如:
str1:ASDFGHJKL
str2:ADFGH
查找,第二个字符串里的字符都包含在第一个字符串里,结果为true。
这个题目有好多种解法

  • 第一种:O(m*n)暴力破解法
    针对第二个短字符串在第一个字符串里是否包含
    代码如下:
#include<iostream>
#include<string>
using namespace std;
int compare( string  str1,string str2)//暴力循环破解的方法
{
    int i, j;
    for (i = 0; i < str2.length(); i++)
    {
        for (j = 0; j < str1.length(); j++)
        {
            if (str1[j] == str2[i])
            {
                break;
            }

        }
        if (j == str1.length())
        {
            cout << "false"<<endl;
            return 0;
        }
    }
    cout << "true" << endl;
    return 1;
}
int main()
{
    string str1 = "ASDFGHJKL";
    string str2 = "ADFGHJ";
    compare(str1, str2);
    system("pause");
    return 0;
}

这里写图片描述

  • 第二种: O(m+n)HashTable的方法
    可以根据哈希的思想,建立一个长度为26的数组,初始化为0,先把第二个短字符串每个字符对应放入数组,当数组相应位置为0时,把该位置置为1然后定义一个计数器,给计数器++当第二个字符串遍历完后,开始遍历第一个字符串当相应位置为1,计数器–;当长字符串遍历完后计数器为0 时,证明包含,当计数器不为0时证明不包含。
    代码如下:
#include<iostream>
#include<string>
using namespace std;
int compare(string str1,string str2)//哈希的方法
{
    int hash[26] = { 0 };
    int num = 0;
    for (int j = 0; j < str2.length(); j++)
    {
        int index = str2[j] - 'A';
        if (hash[index] == 0)
        {
            hash[index] = 1;
            num++;
        }
    }
    for (int i = 0; i < str1.length(); i++)
    {
        int index = str1[i] - 'A';//求该字符应该对应数组中的位置
        if (hash[index] == 1)
        {
            hash[index] = 0;
            num--;
            if (num == 0)
            {
                break;
            }
        }
    }
    if (num == 0)
    {
        cout << "true" << endl;
        return 0;
    }
    else
    {
        cout << "false" << endl;
        return -1;
    }
}
int main()
{
    string str1 = "ASDFGHJKL";
    string str2 = "ADFGHJ";
    compare(str1, str2);
    system("pause");
    return 0;
}
  • 第三种:O(m+n)素数的方法
    方法来源

    https://blog.csdn.net/v_JULY_v/article/details/6347454

    你可能会这么想:O(n+m)是你能得到的最好的结果了,至少要对每个字母至少访问一次才能完成这项操作,而上一节最后的俩个方案是刚好是对每个字母只访问一次。

    假设我们有一个一定个数的字母组成字串,我给每个字母分配一个素数,从2开始,往后类推。这样A将会是2,B将会是3,C将会是5,等等。现在我遍历第一个字串,把每个字母代表的素数相乘。你最终会得到一个很大的整数,对吧?
    然后——轮询第二个字符串,用每个字母除它。如果除的结果有余数,这说明有不匹配的字母。如果整个过程中没有余数,你应该知道它是第一个字串恰好的子集了。

1.#include <iostream>  
2.#include <string>  
3.#include "BigInt.h"  
4.using namespace std;  
5.  
6.// 素数数组  
7.int primeNumber[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,  
8.                        61, 67, 71, 73, 79, 83, 89, 97, 101};  
9.  
10.int main()  
11.{  
12.    string strOne = "ABCDEFGHLMNOPQRS";  
13.    string strTwo = "DCGSRQPOM";  
14.  
15.    // 这里需要用到大整数  
16.    CBigInt product = 1;   //大整数除法的代码 
17.  
18.    // 遍历长字符串,得到每个字符对应素数的乘积  
19.    for (int i = 0; i < strOne.length(); i++)  
20.    {  
21.        int index = strOne[i] - 'A';  
22.        product = product * primeNumber[index];  
23.    }  
24.  
25.    // 遍历短字符串  
26.    for (int j = 0; j < strTwo.length(); j++)  
27.    {  
28.        int index = strTwo[j] - 'A';  
29.  
30.        // 如果余数不为0,说明不包括短字串中的字符,跳出循环  
31.        if (product % primeNumber[index] != 0)  
32.            break;  
33.    }  
34.  
35.    // 如果积能整除短字符串中所有字符则输出"true",否则输出"false"。  
36.    if (strTwo.length() == j)  
37.        cout << "true" << endl;  
38.    else  
39.        cout << "false" << endl;  
40.    return 0;  
41.}  

猜你喜欢

转载自blog.csdn.net/weixin_40853073/article/details/82115474