《算法笔记》codeup_100000580_C

思路:

通过字符串匹配算法找到模式在文本中出现的位置,再删除文本中的模式后输出,或者跳过文本中的模式输出

解答:

为了把BF算法分离出来,代码写复杂了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;

int BF2(char txt[], char pat[], int match[]) {
	int i = 0; // txt指针 
	int j = 0; // pat指针 
	int k = 0; // txt中与pat匹配的次数 
	int txt_len = strlen(txt), pat_len = strlen(pat);
	while (i <= txt_len - 1 && j <= pat_len - 1) {
		if (txt[i] == pat[j] || txt[i] == pat[j] - 32 ) {  // 如果文本中的字符与模式中的字符或其大写相同,则本次匹配成功 
			++i;                                           // 文本指针和模式指针都前进一位 
			++j;
			if(j == pat_len) {                             // 如果模式已经遍历完,则表明本轮匹配成功 
				match[k++] = i - pat_len;                  // 将本次匹配的启示位置加入match数组 
				j = 0;                                     // 模式指针重新指向模式首位 
			}
		}
		else {                                             // 当前位置元素不匹配,则本次匹配失败 
			i = i - j + 1;                                 // 文本指针指向本轮匹配起始位置的下一位 
			j = 0;                                         // 模式指针重新指向模式首位
		}
	}
	
	return k;
}

//将输入的字符串全部元素转为小写 
void capital_to_lower (char txt[]) {
	for (int i = 0; txt[i] != '\0'; ++i) {
		if (txt[i] >= 'A' && txt[i] <= 'Z')
			txt[i] += 32;
	}
} 

void print(char txt[], int match[], int match_num, int pat_len) {
	int i = 0;               // 文本指针 
	int j = 0;               // 匹配位置序号 
	int txt_len = strlen(txt);     // 文本长度 
	
	if(txt_len > 0) {              // 如果文本长度大于0,即如果文本不为空 
		if(match_num == 0) {                 // 如果文本中不存在模式 
			for(int i = 0; i <= txt_len - 1; i++) {    // 遍历文本,依次输出空格以外的字符 
				if(txt[i] != ' ')
					printf("%c", txt[i]);
			}
		}
		else {                               // 如果文本中包含模式 
			while(i <= txt_len - 1) {        // 遍历文本 
				if(txt[i] == ' ') {          // 跳过空格 
					i++;
					continue;
				}
				if(i != match[j]) {          // 如果当前位置不是匹配位置  
					printf("%c", txt[i]);       // 输出当前元素 
					i++;                        // 文本指针指向下一位 
				} 
				else {                       // 如果当前位置是匹配位置 
					i += pat_len;               // 指针向前跳过文本中包含的模式 
					if(j < match_num - 1)       // 如果还有匹配位置,则j指向下一个匹配位置 
						j++;                          
				}
			}
		}
	}
	printf("\n");                  // 每一次都要输出换行 
}

int main () {
	char pat[1000];              // 文本字符数组 
	char txt[1000];              // 模式字符数组 
	gets(pat);                   
	capital_to_lower(pat);       // 文本字符数组的元素全部转为小写 
	int pat_len = strlen(pat);
	
	while(gets(txt) != NULL) {
		int match[1000];         // 文本中模式出现的位置 
		int match_num = BF2(txt, pat, match);
		print(txt, match, match_num, pat_len);
	}
	return 0;
} 

坑:

卡在答案50好久,查了一下并回忆了一下以前出现这个错误的情况,大致判断是数组越界了。果不其然,下面部分缺了个continue。

			while(i <= txt_len - 1) {        // 遍历文本 
				if(txt[i] == ' ') {          // 跳过空格 
					i++;
					continue;
				}
				if(i != match[j]) {          // 如果当前位置不是匹配位置  
					printf("%c", txt[i]);       // 输出当前元素 
					i++;                        // 文本指针指向下一位 
				} 
				else {                       // 如果当前位置是匹配位置 
					i += pat_len;               // 指针向前跳过文本中包含的模式 
					if(j < match_num - 1)       // 如果还有匹配位置,则j指向下一个匹配位置 
						j++;                          
				}
			}

当文本以空格结尾时,第一个if跳过空格后i指向超过数组的位置,此时文本已经遍历完,不应该再访问文本字符数组,但由于没有continue,while循环继续往下走,当前位置在超过了数组,必然不是匹配位置,于是进入if,访问超过文本大小的位置,数组越界。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值