问题描述:
给定两个字符串S1和S2,要求判定S2是否能够被S1做循环移动得到的字符串包含。如S1=AABCD和S2=CDAA,则S1循环移动后包含S2,返回true;S1=ABCD和S2=ACBD,则S1循环移动后不包含S2,返回false
解题思路:
1)可以发现,S1循环移动后的结果肯定包含在字符串S1+S1中,所以可以直接判断S2是否包含在字符串S1+S1中,这样需要的空间复杂度较大,但是只需要做一次contains的查询,时间复杂度较小。 (参考《编程之美》)
2)可以把字符串S1看做一个循环列表,这样只要重新设计contains函数就可以,空间复杂度和时间复杂度都很小。
代码如下:
/** *@author MWD * 2013-9-20 */ #include<stdio.h> #include<string.h> #include<stdlib.h> bool rotateContain1(char*,char*); bool rotateContain2(char*,char*); int main(){ char src[] = "AABBCD"; char des[] = "CDAA"; bool flag1 = rotateContain1(src,des); bool flag2 = rotateContain2(src,des); if(flag1 == true) printf("rotatecontain1 find!\n"); else printf("rotateContain1 can not find!\n"); if(flag2 == true) printf("rotatecontain2 find!\n"); else printf("rotateContain2 can not find!\n"); getchar(); return 0; } /** * 可以将问题转化为判断des是否在字符串src+src中,增加了空间复杂度,减小了时间复杂度 */ bool rotateContain1(char* src,char* des){ int len1 = strlen(src); int len2 = strlen(des); char * str = (char*)malloc(sizeof(char)*(2*len1)); int i=0; for(int j=0;j<len1;j++){ str[i++] = src[j]; } for(int j =0;j<len1;j++) str[i++] = src[j]; if(strstr(str,des)!= NULL) return true; else return false; } /** * 可以将 */ bool rotateContain2(char* src,char* des){ int len1 = strlen(src); //字符串src的长度 int len2 = strlen(des); //字符串des的长度 int j,k; if(!len2) return true; for(int i=0;i<len1;i++){ j = 0; //如果第一个字符相等,那么就继续比较剩下的字符 if(src[i] == des[j]){ for(;j<len2;j++){ k = (i+j)%len1; //将循字符数组看做循环列表 if(src[k] != des[j]) break; } if(j == len2) return true; else return false; } } //比较完所有的字符,没有找到包含,那么就不存在包含关系 return false; }