字符串包括

摘要:
字符串包括标题:如果有一个由各种字母组成的字符串a和另一个字符串B,则字符串B中的字母数量相对较少。如果假设为真,则称为假,否则将不处理;最后,遍历存储阵列。假设所有元素都为false,这意味着短字符串和长字符串中的所有元素都具有。② 遍历长字符串以获得每个字符对应素数的乘积。

字符串包括

题目:如果这有一个各种字母组成的字符串A,和另外一个字符串B,字符串里B的字母数相对少一些。什么方法能最快的查出全部小字符串B 里的字母在大字符串A里都有?
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
a是长字符串,b是短字符串
方法一:双循环比較法(轮询法)
针对b中的每个字符。逐个与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;
}

复杂度:O(n*m)时间开销过大
方法二、排序+轮询法

先对两个字符串的字母进行排序。之后同一时候对两个字符串依次线性扫描轮询
伪代码:

//注意AB中可能包括反复字符,所以注意A下标不要轻易移动,这样的方法改变了字符串,假设不想改变能够选择复制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;
}

注意:这里攻克了一个假设存在同样字符问题,一定要注意不能直接i++。j++,字符类题目一定要注意考虑字符同样的情况。该算法的复杂度为O(mlogm) + O(nlogn) + O(m+n)
方法三:数组存储法

首先标记短字符串中有哪些字符,则在store数组中标记为true,store数组事实上就是起到一个映射的作用;之后遍历长字符串。假设为true的则辩称false,否则不处理;最后遍历store数组,假设所有元素都是false那么说明短字符串中元素长字符串中所有有。否则没有。
伪代码:

bool store[maxn];
memset(store, false, 58);
for(i = 0; i < len1; i++)
{
    store[short[i] - 65] = true;
}

for(i = 0; i < len2; i++)
{
    if(store[long[i] - 65] != false)
        store[long[i] - 65] = false;
}

for(i = 0; i < maxn; i++)
{
    if(store[i] != false)
    {
        短字符中有长字符中没有的字符;
        break;
    }
    if(i == len2-1)//事实上也能够通过return来完毕
    {
        短字符中没有长字符中没有的字符;
    }
}

复杂度为O(m+n)
方法四:O(n)到O(m+n)的素数方法

思路:
① 定义最小的26 个素数分别与字符'A'到'Z'相应。
② 遍历长字符串,求得每一个字符相应素数的乘积。
③ 遍历短字符串,推断乘积是否能被短字符串中的字符相应的素数整除。


伪代码:

//这种方法仅仅有理论意义,因此整数乘积非常大,有溢出风险bool StringContain(string &a, string &b)
{
    const 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,91,97,101};
    int product = 1;

    //遍历长字符串
    for(int i = 0; i < a.length(); i++)
    {
        int index = a[i] - 'A';
        product *= primeNumber[index];
    }

    //遍历短字符串
    for(int j = 0; j < b.length(); j++)
    {
        int index = b[j] - 'A';
        if(product % primeNumber[index] != 0)
            return false;
    }
    return true;
}

纸质手写代码易犯错误:
① 91不是素数
② product初始化为1,不是0
待改进地方
这个程序尽管非常巧妙。运用数学知识减少了时间复杂度
1.仅仅考虑大写字符,假设考虑小写字符和数组的话,素数数组须要很多其它素数
2.没有考虑反复的字符,能够增加推断反复字符的辅助数组。
方法五、哈希表

思路1:将短的字符串存储在哈希表hashTable中,对于字符串中字符为1,而且用num统计1的个数cnt之后再扫描长字符串的每一个字符。若原来hashTable[*pHashKey]为1时。我们改动为0。且将cnt减去1,否则不处理;若cnt == 0或者扫描结束,循环结束;
伪代码:

bool  is_contain(string LongStr, string ShortStr)
{
    bool is_pipei = false;
    const  int tableSize = 256;
    unsigned int hashTable[tableSize];
    int i,cnt = 0;

    for(i = 0; i < tableSize; i++)
    {
        hashTable[i] = 0;
    }

    for(i = 0; i < ShortStr.length(); i++)
    {
        hashTable[i] = 1;
        cnt ++;
    }

    for(i = 0; i < LongStr.length(); i++)
    {
        if(hashTable[LongStr[i]] == 1)
        {
            hashTable[LongStr[i]] = 0;
            cnt --;
        }
    }
    if(cnt == 0)
    {
        is_pipei = true;
    }
    return is_pipei;
}

思路2:事实上能够依据存储长的字符串,对于哈希表值为1,之后再去扫描短字符串中的每一个字符。假设存在哈希表值为0。则说明短字符中存在长字符中不含有的字符。反之不存在。
伪代码:

bool is_contain(char *src, char *des) 
{ 
    bool is_pipei = true; //创建一个哈希表,并初始化
    const int tableSize = 256; 
    int hashTable[tableSize]; 
    int len1,len2,i; 
    for(i=0; i< tableSize; i++) 
        hashTable[i] = 0; 

    len1 = strlen(src); 
    for(i=0; i< len1; i++) 
        hashTable[src[i]] = 1; 
    len2 = strlen(des); 
    for(i=0; i< len2; i++) 
        { 
            if(hashTable[des[i]] == 0) 
                is_pipei = false; //匹配失败 
        } 

        return is_pipei; //匹配成功
}

思路3、先轮询长字符串,用位运算计算出一个”签名“,再用短字符串中字符去长字符串中去查找

//最好的方法。时间复杂度O(n+m) 空间复杂度为O(1)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;
}

这样的方法实质上是用整数替代了哈希表。时间复杂度O(n+m) 空间复杂度为O(1)
最优质的算法


免责声明:文章转载自《字符串包括》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【Dubbo实战】基础学习篇(一)unity事件机制下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

张孝祥java高新技术 --- jkd1.5 新特性 -- 精华总结

1. 抽象方法的使用   如果一个方法中大量出现if语句, 那么, 就应该考虑使用抽象来处理. 如下例: package com.lxl; public class Weekend { //周日 public static Weekend SUN = new Weekend(); //周一...

多个datagridview之间互相传值

 一个winform程序,有两个窗体,一个是住窗体,一个是子窗体。主窗体中有一个button按钮和一个datagridview控件。点击button按钮弹出子窗体,子窗体如图:这其中涉及到两张表,一张是生产产品的供应商信息表,一张是产品信息表。主窗体查询的是供应商信息表,子窗体左边的datagridview查询的是产品信息表。当点击中间的“=>”按钮...

thrift在hive中的应用

thrift在hive中的应用 » ORATEA thrift在hive中的应用 hadoop添加评论 六272011 thrift是一种可伸缩的跨语言服务的发展软件框架。它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C + +,C#,Java,Python和PHP和Ruby结合。thrift是facebook开...

C#实现JSON序列化与反序列化

JSON(JavaScript Object Notation)——JavaScript对象表示法,是JavaScript用来处理数据的一种格式,大部分是用来处理JavaScript和web服务器端之间的数据交换,把后台web服务器的数据传递到前台,然后使用JavaScript进行处理,例如ajax等,是独立于语言和平台的轻量级的数据交换格式。 JSO...

scala 学习笔记(07) 一等公民的函数

在scala中一切皆对象,一切皆函数,函数跟Int,String、Class等其它类型是处于同等的地位,换句话说,使用函数跟使用普通的类型一样,没什么区别,因此: 1、函数可以赋值给变量,可以当参数传递 def helloWorld(msg: String): Unit = { println("Hello," + msg) }...

CodeSmith使用方法

CodeSmith(1):使用和语法简介 http://www.cnblogs.com/duanzt/archive/2005/12/31/308665.html 下载: 官方网站:http://www.codesmithtools.com/ 5.0破解文件下载:http://kewlshare.com/dl/0538fcf454d3/CodeSmit...