字符串左右旋,实际上就是左移右移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函数用于判断后者是否是前者的子串。