OJ地址:​​https://vjudge.net/problem/OpenJ_Bailian-3711​

对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾形成新的字符串。

给定两个字符串s1和s2,要求判定其中一个字符串是否是另一字符串通过若干次循环移位后的新字符串的子串。例如CDAA是由AABCD两次移位后产生的新串BCDAA的子串,而ABCD与ACBD则不能通过多次移位来得到其中一个字符串是新串的子串。

Input

一行,包含两个字符串,中间由单个空格隔开。字符串只包含字母和数字,长度不超过30。

Output

如果一个字符串是另一字符串通过若干次循环移位产生的新串的子串,则输出true,否则输出false。

Sample Input

AABCD CDAA

Sample Output

true

程序代码:

我想的是使用string将字符串复制一倍,这样就代替了字符串的循环,之后再使用find函数进行字符串子串匹配。但是提交显示错误,原因未知:

string常用用法请参考:string的常用用法详解

OpenJ_Bailian - 3711  字符串移位包含问题_字符串

#include<iostream>
#include<string>
using namespace std;
int main(){
string str1,str2,str3,str4;
cin>>str1>>str2;
str3=str1+str1;
str4=str2+str2;
if((str3.find(str2)==-1)&&(str4.find(str1)==-1)){
cout<<"false"<<endl;
}else{
cout<<"true"<<endl;
}
return 0;
}

正确:

#include<cstdio>
#include<cstring>
using namespace std;
int main(){
char str1[31],str2[31],tmp[31];
scanf("%s%s",str1,str2);

int s1 = strlen(str1);
int s2 = strlen(str2);
int x;
if(s1 < s2){
tmp[31] = str1[31];
str1[31] = str2[31];
str2[31] = tmp[31];
x=s1;
s1=s2;
s2=x;
}
int i,j;
for(i=0;i<s1;i++){
for(j=0;i<s2;j++){
if(str1[(i+j)%s1]!=str2[j])
break;
}
if(j==s2)
break;
}
if(j==s2)
printf("true\n");
else
printf("false\n");
return 0;
}

题中的str1[(i+j)%s1]可以实现字符串的循环:(i+j)%s1 = i%s1+j%s1;(i%s1的值为0、1、2、 . . . . . . s1-2、s1-1、0;j%s1的值为0、1、2、...... s2-1)。

运行结果:

OpenJ_Bailian - 3711  字符串移位包含问题_字符串_02