搜索
您的当前位置:首页正文

字符串包含

来源:二三娱乐

题目描述

给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短。请问,如何最快地判断字符串B中所有字母是否都在字符串A里?

为了简单起见,我们规定输入的字符串只包含大写英文字母,请实现函数bool StringContains(string &A, string &B)

比如,如果是下面两个字符串:
String 1:ABCD
String 2:BAD
答案是true,即String2里的字母在String1里也都有,或者说String2是String1的真子集。

如果是下面两个字符串:
String 1:ABCD
String 2:BCE
答案是false,因为字符串String2里的E字母不在字符串String1里。

求解

解法1 暴力轮询

对string2中的每一个字符,逐个与string1中的每个字符比较,看它是否在string1中。
假设string1长度为n,string2长度为m,那么这个算法的时间复杂度为O(n*m)。
代码如下:

bool stringContain0(string &a, string &b) {
    for(int i = 0; i < b.length(); i++) {
        int j;
        for(j = 0; (j < a.length() && a[j] != b[i]); j++)
            ;
        if (j >= a.length())
            return false;
    }
    return true;
}

解法2 首先排序,利用有序性进行检验

首先对两个字符串中的字母进行排序O(mlogm)+O(nlogn),然后进行线性扫描O(m+n)。

bool stringContain(string &a, string &b) {
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    for (int pa = 0, pb = 0; pb < b.length();) {
        while((pa<a.length()) && (a[pa] < b[pb])) {
            pa++;
        }
        if ((pa >= a.length()) || (a[pa] > b[pb])) {
            return false;
        }
        pb++;
    }
    return true;
}

解法3 利用素数不能被其他数字整除的性质

1.按照从小到大的顺序,用26个素数分别与字符'A'到'Z'一一对应。
2.遍历长字符串,求得每个字符对应素数的乘积。
3.遍历短字符串,判断乘积能否被短字符串中的字符对应的素数整除。
4.输出结果。
时间复杂度为O(m+n)

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 f = 1;
    for (int i = 0; i < a.length(); i++) {
        int tmp = p[ a[ i ] - 'a' ];
        if (f % tmp) {
            f *= tmp;
        }
    }
    for (int i = 0; i < b.length(); i++) {
        int tmp = p[ b[ i ] - 'a' ];
        if (f % tmp) {
            return false;
        }
    }
    return true;
}

解法4

可以使用hash完成,首先对长字符串进行轮询,放入hash,然后对短字符串进行轮询,如果hash中没有则返回失败。如果全都有则成功。
这里由于只有26bit所以使用一个int代替hash。空间复杂度为O(1)。时间复杂度为O(m+n)。

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;
}

总的测试程序如下:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool stringContain0(string &a, string &b);
bool stringContain1(string &a, string &b);
bool stringContain2(string &a, string &b);
bool stringContain3(string &a, string &b);
int main(void) {
    string a = "fqwer";
    string b = "rewq";
    bool c = stringContain0(a, b);
    cout << c << endl;
    c = stringContain1(a, b);
    cout << c << endl;
    c = stringContain2(a, b);
    cout << c << endl;
    c = stringContain3(a, b);
    cout << c << endl;
}
bool stringContain0(string &a, string &b) {
    for(int i = 0; i < b.length(); i++) {
        int j;
        for(j = 0; (j < a.length() && a[j] != b[i]); j++)
            ;
        if (j >= a.length())
            return false;
    }
    return true;
}
bool stringContain1(string &a, string &b) {
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    for (int pa = 0, pb = 0; pb < b.length();) {
        while((pa<a.length()) && (a[pa] < b[pb])) {
            pa++;
        }
        if ((pa >= a.length()) || (a[pa] > b[pb])) {
            return false;
        }
        pb++;
    }
    return true;
}
bool stringContain2(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 f = 1;
    for (int i = 0; i < a.length(); i++) {
        int tmp = p[ a[ i ] - 'a' ];
        if (f % tmp) {
            f *= tmp;
        }
    }
    for (int i = 0; i < b.length(); i++) {
        int tmp = p[ b[ i ] - 'a' ];
        if (f % tmp) {
            return false;
        }
    }
    return true;
}

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;
}
Top