学习札记:判断左右旋

字符串左右旋,实际上就是左移右移k个字符,将移除的字符接到相反位置的行为。例如:
“hello world"左移4位,就是"o worldhell”
“SouthEast University"右移7位,就是"versitySouthEast Uni”

给定两段字符串,怎样判断这两段是否可以通过左右旋互相得到呢?
最先,如果两字符串长度都不相等,那肯定不能自旋得到。
如果长度相等,这个任务可以拆分为:
①对其中一段左(右)旋。向左向右没有关系,因为向左k位其实就是向右strlen(str)-k位。
②每旋一个字符,做一次比较。比较当前二者是否完全一样。如果完全一样,那就是可以通过自旋得到。

因此,首先,至少要实现的功能是:比较两个字符串是否相同。

我们用strcmp(*str1,*str2)完成这个功能。
如果str1与str2完全相同,strcmp函数会输出1。其实也可以自己实现这个功能,只要比较每一位的ASCII码是否相同就可以比较字符串是否相同了。

然后,我们要开始自旋。在此选用左旋,每次左旋1位,旋转上限是strlen(str1)次(当然strlen(str2)次也一样,因为我们已经确保了两字符串长度相等);只要其中有一次str1和str2相同,就终止左移。

代码如下:

int compare(char* ch1, char* ch2) {
	int flag = 0;
	if(strlen(ch1)!=strlen(ch2)) return 0;//不等长则肯定不是左右旋结果
	else {
		for (int i = 0; i < strlen(ch1); i++)//等长则开始做旋转动作
		{
			char temp = ch1[0];//提取第一个字符
			for (int j = 0; j < strlen(ch1) - 1; j++)
			{
				ch1[j] = ch1[j + 1];//字符串整体前移
			}
			ch1[strlen(ch1) - 1] = temp;//第一个字符填入最后一个空隙,相当于左旋一位
			if (strcmp(ch1, ch2) == 0) {//用strcmp函数比较字符串,若返回值为0则意味着字符串完全相同
				flag = 1; break;//输出1,然后停止左旋
			}
			else flag = 0;//否则输出0,继续左旋直至flag=1或左旋一周
		}
		return flag;
	}
}
int main() {
	char ch1[] = "abcdefg";
	char ch2[] = "higklmf";
	char ch3[] = "hello world";
	char ch4[] = "orldhello w";
	cout << compare(ch1, ch2)<<" " << compare(ch3, ch4);
}

当然,我们还有更简单的办法。

如果两个字符串可由自旋而得到,那么它们必定处在一个“循环”中。
拿"SouthEast University"为例,它右旋7位就是"versitySouthEast Uni",而让我们考察一下"SouthEast University"这个字符串重复两遍的结果吧:

“SouthEast UniversitySouthEast University”

你会发现,右旋后的字符串就在这个重复了两次构成的大字符串内部:

“SouthEast Uni(versitySouthEast Uni)versity”

所以,是否可以把其中一个字符串重复一遍,将第二个字符串与新的大字符串比较,若在大字符串内检出了第二段字符串,就说明可以自旋得到呢?

答案是肯定的,而且会挺简单:

int compare(const char * src, char * find)
{
	char tmp[256] = { 0 }; //用一个辅助空间将原字符串做成两倍原字符串
	strcpy(tmp, src); //先拷贝一遍
	strcat(tmp, src); //再连接一遍
	return strstr(tmp, find) != NULL; //看看找不找得到
}

strcpy函数用于拷贝src函数到tmp字符串内;strcat函数用于将两个字符串连接;strstr函数用于判断后者是否是前者的子串。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值