字符串移位包含问题

给定两个字符串分别是:AABCD,CDAA,如果对字符串AABCD进行循环移位,移动的位数在AABCD的长度范围内,在所有的移位情况之中,移位后的字符串是否包含第二个字符串,也就是第二个字符串是第一个字符串移位后的字串。当然移动0位的情况不算,比如AABCD,AABC, 这不用移位,第二个字符串就是第一个字符串的字串。有三种方法来解决这个问题,最后会对三种方法做一个对比。

1,brute-force方法:就是通常的暴力方法,对给定的字符串每次左移移位,然后在移位后的字符串中查找第二个字符串,如果没有找到,对第一个字符串再接着移位.....直到在移位后的字符串中可以找到第二个字符串,或者移动的次此正好和字符串的长度相等的时候,就是说在移位后的字符串中没有找到给定的第二个字符串,有了思路,给出代码:

int is_contain(char *p_str, char *s_str) {
	int len_p = strlen(p_str);
	int len_s = strlen(s_str);
	int i, j;
	char temp;
	for(i = 0; i < len_p; i++) {
		temp = p_str[0];
		for(j = 0; j < len_p - 1; j++) {
			p_str[j] = p_str[j + 1];
		}
		p_str[j] = temp;
		if(strncmp(p_str, s_str, len_s) == 0) {
			return 1;
		}
	}
	if(i == len_p) {
		return 0;
	}
}

2,就是利用空间复杂度换取时间复杂度的方法:对于每次的移动,我们观察每次移除的字符,分别是A,A,B,C,D,如果把每次移除的字符放在原始字符串的后面,就会有如下的结果:AABCDA, AABCDAA, AABCDAAB, AABCDAABC, AABCDAABCD,所有移位之后的最后一个字符串,AABCDAABCD,看看有什么特点,它居然包含我们要找的字符串CDAA,可能有人认为这是一种巧合,那再看一个不成立的例子:ABCD, CDBA, ABCD移位并添加后的字符串是ABCDABCD, 可以看到ABCDABCD中有CDAB,但是没有CDBA,故这个算法还是正确的。但是要浪费一点空间。给出核心代码:

int is_contain2(char *p_str, char *s_str) {
	int len_p = strlen(p_str);
	char *temp = (char*)malloc(2 * len_p + 1);
	strcpy(temp, p_str);
	strcpy(temp + len_p, p_str);
	if(strstr(temp, s_str)) {
		return 1;
	} else {
		return 0;
	}
}
3,有什么方法既可以节省空间,又可以节省时间呢。大家还记得mod运算吧,那么有这么一种想法,通过不断的对字符串索引值进行模运算,是不是表示了循环移位呢。可能很晦涩,不是很容易理解。这种算法的基本思路就是在第一个字符串中首先找到第二个字符串首字母出现的位置,比如AABCD, CDAA两个字符串,CDAA早AABCD中首次出现的位置是第3位,然后第一个字符串便从第3位开始和第二个字符串比较,但是在比较过程中,索引的值可能越界,怎么办呢,进行模运算,这样就相当于在循环移位了。可能解释的不是很好,直接看代码吧:,这个代码还有问题,如果对待这种"password", "swordpas"这种情况就运行不正确。

int is_contain3(char *p_str, char *s_str) {
	int i = 0, j = 0;
	int len_p = strlen(p_str);
	int len_s = strlen(s_str);
	while(i < len_p && p_str[i] != s_str[j]) {
		i++;
	}
	if(i == len_p) {
		return 0;
	}
	while(i < len_p && j < len_s) {
		if(p_str[i] != s_str[j]) {
			return 0;
		}
		j++;
		i = (i + 1) % len_p;
	}
	if(j == len_s) {
		return 1;
	} else {
		return 0;
	}
}

第一个算法的时间复杂度为O(n^2),空间复杂度为O(1),第二个算法的时间复杂度和空间复杂度均为:O(n),第三个算法的时间复杂度和空间复杂度分别为:O(n), O(1).

下面是正确的代码,能够处理重复字符的情况:

int is_contain(char *p_str, char *s_str) {
	int repeat_count = 0;
	int total_count = 0;
	int count = 0;
	int index = -1;
	char first_letter;
    int i = 0, j = 0;  
    int len_p = strlen(p_str);  
    int len_s = strlen(s_str);
	first_letter = *s_str;
	while(j < len_s) {
		if(s_str[j] == first_letter) {
			repeat_count++;
		} else {
			break;
		}
		j++;
	}
	j = 0;
	while(j < len_s) {
		if(s_str[j] == first_letter) {
			total_count++;
		}
		j++;
	}
    while(i < len_p) {  
		if(p_str[i] == first_letter) {
			count++;
			if(count == (total_count - repeat_count)) {
				index = i + 1;
				break;
			}
		}
		i++;
    }  
    if(index == -1) {  
        return 0;  
    }  
	j = 0;
	i = index;
    while(i < len_p && j < len_s) {  
        if(p_str[i] != s_str[j]) {  
            return 0;  
        }  
        j++;  
        i = (i + 1) % len_p;  
    }  
    if(j == len_s) {  
        return 1;  
    } else {  
        return 0;  
    }  
} 

你可能感兴趣的:(字符串移位包含问题)