编程艺术 - 第二章 第一节、俩个字符串是否包含

2021/5/2 1:25:26

本文主要是介绍编程艺术 - 第二章 第一节、俩个字符串是否包含,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目

假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字
母数相对少一些。从算法是讲,什么方法能最快的查出所有小字符串里的字母在大字符串里
都有?
比如,如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOM
答案是 true,所有在 string2 里的字母 string1 也都有。
如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOZ
答案是 false,因为第二个字符串里的 Z 字母不在第一个字符串里

分析

暴力法

最简单的思路就是,让子串中的每一个字符都去与目标串的字符去匹配,匹配成功就继续匹配,若匹配失败直接false。时间复杂度为O(n^2),空间复杂度为O(1);
C

#include<stdio.h>
#include<string.h>
#include<stdbool.h>

//暴力求解
bool CompareSting(char* dest, int dlen, char* sub, int slen)
{
	int i = 0;//目标串指针
	int j = 0;//子串指针

	for (j = 0; j < slen; j++)//O(n^2)
	{
		int flag = 0;
		for (i = 0; i < dlen; i++)
		{
			if (sub[j] == dest[i])
			{
				flag = 1;
				break;
			}
		}

		if (flag == 0)
		{
			return false;
		}
	}

	return true;
}


int main()
{
	char dest[] = "ABCDEFGHLMNOPQRS";

	char sub[] = "DCGSRQPOM";

	int dlen = sizeof(dest) / sizeof(dest[0]) - 1;
	int slen = sizeof(sub) / sizeof(sub[0]) - 1;

	bool ret = CompareSting(dest, dlen, sub, slen);

	if (ret)
	{
		printf("true\n");
	}
	else
	{
		printf("false\n");
	}

	return 0;
}

排序+比较

暴力法高额的时间复杂度是因为字符是无序的。所以这里我们先排序后一遍匹配就可以了。这里时间复杂度最大就是排序算法的,这里用的是qsort库排序算法。时间复杂度O(n*logn)
C

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>

int compar_char(const void* e1, const void* e2)
{
	return *(char*)e1 - *(char*)e2;
}

bool CompareSting(char* dest, int dlen, char* sub, int slen)
{
	//先让目标串和子串排序,以便后面对比
	qsort(dest, dlen, sizeof(dest[0]), compar_char);//O(n*logn)
	qsort(sub, slen, sizeof(sub[0]), compar_char);

	int i = 0;//目标串指针
	int j = 0;//子串指针

	for(i = 0; i < dlen; i++)
	{
		if (sub[j] == dest[i])//相等,子串指针移动
		{
			j++;
		}

		if (j < slen)//若在目标串走完前,发现子串匹配完,就表示成功了
		{
			return true;
		}
	}
	return false;
}


int main()
{
	char dest[] = "ABCDEFGHLMNOPQRS";

	char sub[] = "DCGSRQPOM";

	int dlen = sizeof(dest) / sizeof(dest[0]) - 1;
	int slen = sizeof(sub) / sizeof(sub[0]) - 1;

	bool ret = CompareSting(dest, dlen, sub, slen);

	if (ret)
	{
		printf("true\n");
	}
	else
	{
		printf("false\n");
	}

	return 0;
}

在这里插入图片描述

哈希表

这里题目并没有说只有大写,为了保险起见,我用了128大小的数组来表示。
把子串中存在的字符以字符值对应数组下标,数组中存1来表示该字符存在。
然后再遍历目标串,把目标串的字符对应的下标存的值均修改为0。
然后再遍历一遍数组,只要发现还有1的值,就便是匹配失败,否则匹配成功。
C

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>

//哈希表 - 数组
bool CompareSting(char* dest, int dlen, char* sub, int slen)
{
	int ASC[128] = { 0 };
	int i = 0;

	//将子串中所有的字母放入哈希表
	for (i = 0; i < slen; i++)
	{
		ASC[sub[i]] = 1;
	}

	//用目标串来拿出哈希表  
	for (i = 0; i < dlen; i++)
	{
		ASC[dest[i]] = 0;
	}


	//遍历哈希表,若发现还没拿出完,就是false,
	for (i = 0; i < 128; i++)
	{
		if (ASC[i] != 0)
		{
			return false;
		}
	}

	return true;
}


int main()
{
	char dest[] = "ABCDEFGHLMNOPQRS";

	char sub[] = "DCGSRQPOM";

	int dlen = sizeof(dest) / sizeof(dest[0]) - 1;
	int slen = sizeof(sub) / sizeof(sub[0]) - 1;

	bool ret = CompareSting(dest, dlen, sub, slen);

	if (ret)
	{
		printf("true\n");
	}
	else
	{
		printf("false\n");
	}

	return 0;
}

本章完!



这篇关于编程艺术 - 第二章 第一节、俩个字符串是否包含的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程