【C语言】判断一个字符串是否为另外一个字符串旋转之后的字符串

一.前言

本文章将介绍两种方法(比较字符和字符串拼接和搜索)来实现判断一个字符串是否为另外一个字符串旋转之后的字符串。

二.题目

使用写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串

例如:
给定s1 =AABCD和s2 = BCDAA
返回1给定s1=abcd和s2=ACBD,返回0.

注意
AABCD左旋一个字符得到ABCDA

AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAAB

三.题目分析与代码展示

1.比较字符

比较字符的方法是通过逐个比较两个字符串的字符来判断是否为旋转字符串。

思路分析

  1. 比较两个字符串的长度,如果长度不相等,那么它们一定不是旋转字符串,直接返回0。
  2. 在字符串s1中寻找字符串s2的第一个字符出现的位置。我们可以使用一个循环来遍历字符串s1的每个字符,当找到与s2的第一个字符相等的字符时,我们记录下它的位置,并跳出循环。
  3. 从记录的位置开始,逐个比较s1和s2的字,。其中我们可以使用取模运算来实现循环比较。
  4. 如果在比较过程中发现有任何一个字符不相等,就说明s2不是s1的旋转字符串,直接返回0。如果所有字符都相等,说明s2是s1的旋转字符串,返回1。

代码展示

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

// 判断字符串是否为旋转字符串
int isRotation(char*s1,char*s2) 
{
	int len1 = strlen(s1);
	int len2 = strlen(s2);

	// 长度不相等,则一定不是旋转字符串
	if (len1 != len2) 
	{
		return 0;
	}

	// 找到字符串 s2 的第一个字符在 s1 中的位置
	int startIndex = -1;
	for (int i = 0; i < len1; i++) 
	{
		if (s1[i] == s2[0]) 
		{
			startIndex = i;
			break;
		}
	}

	// 如果没有找到匹配的字符,则不是旋转字符串
	if (startIndex == -1) 
	{
		return 0;
	}

	// 检查 s1 从 startIndex 开始的子串是否与 s2 相等
	for (int i = 0; i < len2; i++)
	{
		if (s1[(startIndex + i) % len1] != s2[i]) 
		{
			return 0;
		}
	}

	return 1;
}

int main() 
{
	char s1[] = "AABCD";
	char s2[] = "BCDAA";
	printf("%d\n", isRotation(s2, s1));  // 输出:1

	char s3[] = "abcd";
	char s4[] = "ACBD";
	printf("%d\n", isRotation(s4, s3));  // 输出:0

	return 0;
}

难点解疑 ((startIndex + i) % len1详解)

  • startIndex 是字符串 s1 中与字符串 s2 的第一个字符匹配的位置。

  • i 是循环变量,用于遍历字符串 s2 的每个字符。

  • len1 是字符串 s1 的长度。

在这个表达式中,(startIndex + i) 是一个新的索引,它表示字符串 s1 中与 s2 当前字符对应的位置。% 运算符将这个索引除以 len1 并返回余数。

这个取模运算的目的是使得字符串 s1 可以循环遍历。当 (startIndex + i) 大于或等于 len1 时,取模运算会将结果回绕到字符串 s1 的起始位置,继续进行比较。

举个例子

假设 s1 是 “ABCDEF”,s2 是 “DEFABC”,则在这个例子中,我们可以找到 startIndex 是 3(即字符 ‘D’ 在
s1 中的位置)。然后,循环变量 i 从 0 开始遍历 s2 中的每个字符。在第一次循环中,(startIndex + i)
3,取模运算得到 3,对应 s2 中的第一个字符 'D’。在下一次循环中,(startIndex + i) 是 4,取模运算得到
4,对应 s2 中的第二个字符 'E’。
当(startIndex + i)是6的时候,取模运算得到0,对应 s2 中的第4个字符 'A’。依此类推,直到遍历完整个 s2 字符串。

这样,我们可以通过取模运算来实现字符串的循环遍历,以便逐个比较 s1 和 s2 中对应位置的字符。

问题解决

在这里插入图片描述

发布文章后就有人提出了这样的问题,也很感谢这位大佬能及时提出我的问题,如果还有问题请大家提出。

这段代码中的问题是在查找字符串 s2 的第一个字符在字符串 s1 中的位置时,只找到了首次出现的匹配字符的位置。因此,对于某些特定情况下的旋转字符串,可能会导致误判。

解决方案是修改查找过程,使其能够找到所有匹配字符的位置,并逐个判断以确保整个子串都匹配成功。以下是修正后的代码示例:


// 判断字符串是否为旋转字符串
int isRotation(char* s1, char* s2) 
{
	int len1 = strlen(s1);
	int len2 = strlen(s2);

	// 长度不相等,则一定不是旋转字符串
	if (len1 != len2) 
	{
		return 0;
	}

	// 找到字符串 s2 的第一个字符在 s1 中的位置的数组
	int startIndex[256];
	int count = 0;

	for (int i = 0; i < len1; i++) 
	{
		if (s1[i] == s2[0]) 
		{
			startIndex[count++] = i;
		}
	}

	// 如果没有找到匹配的字符,则不是旋转字符串
	if (count == 0) 
	{
		return 0;
	}

	// 逐个判断以各个可能的起始位置为开始的子串是否与 s2 相等
	for (int j = 0; j < count; j++) 
	{
		int index = startIndex[j];
		int match = 1;  // 标志位,判断子串是否完全匹配

		for (int i = 0; i < len2; i++) 
		{
			if (s1[(index + i) % len1] != s2[i]) 
			{
				match = 0;
				break;
			}
		}

		if (match) 
		{
			return 1;
		}
	}

	return 0;
}

int main() 
{
	char s1[] = "AABCD";
	char s2[] = "ABCDA";
	printf("%d\n", isRotation(s1, s2));  // 输出:1

	char s3[] = "abcd";
	char s4[] = "ACBD";
	printf("%d\n", isRotation(s3, s4));  // 输出:0

	return 0;
}

运行结果如下:
在这里插入图片描述修正后的代码中,在找到字符串 s2 第一个字符在字符串 s1 中的位置时,将所有匹配字符的位置都保存在 startIndex 这个数组中。然后,对于每个可能的起始位置,逐个判断以该位置为开始的子串是否与 s2 完全匹配。只有当存在至少一个起始位置可以使得整个子串与 s2 相等时,才返回1表示是旋转字符串。这样修改后的代码能够正确处理包含重复字符的情况,避免了误判。

2.字符串拼接和搜索

思路分析

符串拼接和搜索的方法是通过将原字符串拼接自身,并在拼接后的字符串中搜索目标字符串来判断是否为旋转字符串。

具体思路如下:

  1. 如果s2是s1旋转得到的字符串,那么将两个s1拼接起来形成的新字符串中,必然包含s2作为子串。
  2. 将两个s1拼接起来得到的新字符串记为combined。
  3. 如果s2是s1旋转得到的字符串,则s2必然是combined的一个子串。
#include <stdio.h>
#include <string.h>

int isRotation(char* s1, char* s2) 
{
	int len1 = strlen(s1);
	int len2 = strlen(s2);

	// 判断两个字符串的长度是否相等
	if (len1 != len2)
	{
		return 0;
	}

	// 将s1与自身拼接,组成一个新的字符串
	char combined[256]={};
	strcpy(combined, s1);
	strcat(combined, s1);

	// 判断s2是否是s1的子串,如果是返回1,否则返回0
	return strstr(combined, s2) != NULL;
}

// 测试样例
int main()
{
	char s1[] = "AABCD";
	char s2[] = "BCDAA";
	printf("%d\n", isRotation(s1, s2));  // 输出:1

	char s3[] = "abcd";
	char s4[] = "ACBD";
	printf("%d\n", isRotation(s3, s4));  // 输出:0

	return 0;
}

strstr函数简介

strstr函数是C语言中的字符串函数,用于在一个字符串中查找指定子串的第一次出现位置。

char *strstr(const char *haystack, const char *needle);

参数说明:

  • haystack:要进行查找的字符串。
  • needle:要查找的子串。

返回值:

  • 如果找到了子串,则返回子串在原字符串中的指针;如果未找到子串,则返回NULL。
  • strstr函数会从字符串 haystack 中开始查找子串 needle。如果找到了子串,则返回该子串在原字符串中的指针;如果未找到子串,则返回NULL。

3.两种方法比较

  • 方法一(比较字符)相对更直接和简单,适用于较短的字符串,可以减少额外的内存消耗
  • 方法二(字符串拼接和搜索)则更加高效,适用于较长的字符串,但可能需要更多的内存空间。根据实际情况和需求,可以选择适合的方法来判断字符串是否为旋转字符串

四.尾声

以上就是本文章的所有内容,如果大家有更好的方法,大家可以在评论区讨论或者私信给博主。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值