第2章 带通配符的字符串匹配问题

字符串匹配问题,给定一串字符串,按照指定规则对其进行匹配,并将匹配的结果保存至output数组中,多个匹配项用空格间隔,最后一个不需要空格。

要求:

  1. 匹配规则中包含通配符?和*,其中?表示匹配任意一个字符,*表示匹配任意多个(>=0)字符。
  2. 匹配规则要求匹配最大的字符子串,例如a*d,匹配abbdd而非abbd,即最大匹配子串。
  3. 匹配后的输入串不再进行匹配,从当前匹配后的字符串重新匹配其他字符串。

请实现函数:char* my_find(char  input[],   char rule[])

举例说明

input:abcadefg
rule:a?c
output:abc

input :newsadfanewfdadsf
rule: new
output: new new

input :breakfastfood
rule: f*d
output:fastfood

注意事项:

  1. 自行实现函数my_find,勿在my_find函数里夹杂输出,且不准用C、C++库,和Java的String对象;
  2. 请注意代码的时间,空间复杂度,及可读性,简洁性;
  3. input=aaa,rule=aa时,返回一个结果aa,即可。

    1、本题与上述第三十章的题不同,上题字符串转换成整数更多考察对思维的全面性和对细节的处理,本题则更多的是编程技巧。闲不多说,直接上代码:

 
 
  1. //copyright@cao_peng 2013/4/23   
  2. int str_len(char *a) {  //字符串长度   
  3.     if (a == 0) {  
  4.         return 0;  
  5.     }  
  6.     char *t = a;  
  7.     for (;*t;++t)  
  8.         ;  
  9.     return (int) (t - a);  
  10. }  
  11.   
  12. void str_copy(char *a,const char *b,int len) {  //拷贝字符串 a = b   
  13.     for (;len > 0; --len, ++b,++a) {  
  14.         *a = *b;  
  15.     }  
  16.     *a = 0;  
  17. }  
  18.   
  19. char *str_join(char *a,const char *b,int lenb) { //连接字符串 第一个字符串被回收   
  20.     char *t;  
  21.     if (a == 0) {  
  22.         t = (char *) malloc(sizeof(char) * (lenb + 1));   
  23.         str_copy(t, b, lenb);  
  24.         return t;  
  25.     }  
  26.     else {  
  27.         int lena = str_len(a);  
  28.         t = (char *) malloc(sizeof(char) * (lena + lenb + 2));  
  29.         str_copy(t, a, lena);  
  30.         *(t + lena) = ' ';  
  31.         str_copy(t + lena + 1, b, lenb);  
  32.         free(a);  
  33.         return t;  
  34.     }  
  35. }  
  36.   
  37. int canMatch(char *input, char *rule) { // 返回最长匹配长度 -1表示不匹配    
  38.     if (*rule == 0) { //已经到rule尾端   
  39.         return 0;  
  40.     }  
  41.     int r = -1 ,may;  
  42.     if (*rule == '*') {  
  43.         r = canMatch(input, rule + 1);  // *匹配0个字符   
  44.         if (*input) {  
  45.             may = canMatch(input + 1, rule);  // *匹配非0个字符   
  46.             if ((may >= 0) && (++may > r)) {  
  47.                 r = may;  
  48.             }  
  49.         }  
  50.     }  
  51.     if (*input == 0) {  //到尾端   
  52.         return r;  
  53.     }  
  54.     if ((*rule == '?') || (*rule == *input)) {  
  55.         may = canMatch(input + 1, rule + 1);  
  56.         if ((may >= 0) && (++may > r)) {  
  57.             r = may;  
  58.         }  
  59.     }  
  60.     return r;  
  61. }  
  62.   
  63. char * my_find(char  input[],   char rule[]) {  
  64.     int len = str_len(input);  
  65.     int *match = (int *) malloc(sizeof(int) * len);  //input第i位最多能匹配多少位 匹配不上是-1   
  66.     int i,max_pos = - 1;  
  67.     char *output = 0;  
  68.   
  69.     for (i = 0; i < len; ++i) {  
  70.         match[i] = canMatch(input + i, rule);  
  71.         if ((max_pos < 0) || (match[i] > match[max_pos])) {  
  72.             max_pos = i;  
  73.         }  
  74.     }  
  75.     if ((max_pos < 0) || (match[max_pos] <= 0)) {  //不匹配   
  76.         output = (char *) malloc(sizeof(char));  
  77.         *output = 0;   // \0   
  78.         return output;  
  79.     }  
  80.     for (i = 0; i < len;) {  
  81.         if (match[i] == match[max_pos]) { //找到匹配   
  82.             output = str_join(output, input + i, match[i]);  
  83.             i += match[i];  
  84.         }  
  85.         else {  
  86.             ++i;  
  87.         }  
  88.     }  
  89.     free(match);  
  90.     return output;  
  91. }  
//copyright@cao_peng 2013/4/23
int str_len(char *a) {  //字符串长度
	if (a == 0) {
		return 0;
	}
	char *t = a;
	for (;*t;++t)
		;
	return (int) (t - a);
}

void str_copy(char *a,const char *b,int len) {  //拷贝字符串 a = b
	for (;len > 0; --len, ++b,++a) {
		*a = *b;
	}
	*a = 0;
}

char *str_join(char *a,const char *b,int lenb) { //连接字符串 第一个字符串被回收
	char *t;
	if (a == 0) {
		t = (char *) malloc(sizeof(char) * (lenb + 1)); 
		str_copy(t, b, lenb);
		return t;
	}
	else {
		int lena = str_len(a);
		t = (char *) malloc(sizeof(char) * (lena + lenb + 2));
		str_copy(t, a, lena);
		*(t + lena) = ' ';
		str_copy(t + lena + 1, b, lenb);
		free(a);
		return t;
	}
}

int canMatch(char *input, char *rule) { // 返回最长匹配长度 -1表示不匹配 
	if (*rule == 0) { //已经到rule尾端
		return 0;
	}
	int r = -1 ,may;
	if (*rule == '*') {
		r = canMatch(input, rule + 1);  // *匹配0个字符
		if (*input) {
			may = canMatch(input + 1, rule);  // *匹配非0个字符
			if ((may >= 0) && (++may > r)) {
				r = may;
			}
		}
	}
	if (*input == 0) {  //到尾端
		return r;
	}
	if ((*rule == '?') || (*rule == *input)) {
		may = canMatch(input + 1, rule + 1);
		if ((may >= 0) && (++may > r)) {
			r = may;
		}
	}
	return r;
}

char * my_find(char  input[],   char rule[]) {
	int len = str_len(input);
	int *match = (int *) malloc(sizeof(int) * len);  //input第i位最多能匹配多少位 匹配不上是-1
	int i,max_pos = - 1;
	char *output = 0;

	for (i = 0; i < len; ++i) {
		match[i] = canMatch(input + i, rule);
		if ((max_pos < 0) || (match[i] > match[max_pos])) {
			max_pos = i;
		}
	}
	if ((max_pos < 0) || (match[max_pos] <= 0)) {  //不匹配
		output = (char *) malloc(sizeof(char));
		*output = 0;   // \0
		return output;
	}
	for (i = 0; i < len;) {
		if (match[i] == match[max_pos]) { //找到匹配
			output = str_join(output, input + i, match[i]);
			i += match[i];
		}
		else {
			++i;
		}
	}
	free(match);
	return output;
}

     2、本题也可以直接写出DP方程,如下代码所示:

  1. //copyright@chpeih 2013/4/23   
  2. char* my_find(char  input[],   char rule[])  
  3. {  
  4.     //write your code here   
  5.     int len1,len2;  
  6.     for(len1 = 0;input[len1];len1++);  
  7.     for(len2 = 0;rule[len2];len2++);  
  8.     int MAXN = len1>len2?(len1+1):(len2+1);  
  9.     int  **dp;  
  10.   
  11.     //dp[i][j]表示字符串1和字符串2分别以i j结尾匹配的最大长度   
  12.     //记录dp[i][j]是由之前那个节点推算过来  i*MAXN+j   
  13.     dp = new int *[len1+1];  
  14.     for (int i = 0;i<=len1;i++)  
  15.     {  
  16.         dp[i] = new int[len2+1];  
  17.   
  18.     }  
  19.   
  20.     dp[0][0] = 0;  
  21.     for(int i = 1;i<=len2;i++)  
  22.         dp[0][i] = -1;  
  23.     for(int i = 1;i<=len1;i++)  
  24.         dp[i][0] = 0;  
  25.   
  26.     for (int i = 1;i<=len1;i++)  
  27.     {  
  28.         for (int j = 1;j<=len2;j++)  
  29.         {  
  30.             if(rule[j-1]=='*'){  
  31.                 dp[i][j] = -1;  
  32.                 if (dp[i-1][j-1]!=-1)  
  33.                 {  
  34.                     dp[i][j] = dp[i-1][j-1]+1;  
  35.   
  36.                 }  
  37.                 if (dp[i-1][j]!=-1 && dp[i][j]<dp[i-1][j]+1)  
  38.                 {  
  39.                     dp[i][j] = dp[i-1][j]+1;  
  40.   
  41.                 }  
  42.             }else if (rule[j-1]=='?')  
  43.             {  
  44.                 if(dp[i-1][j-1]!=-1){  
  45.                     dp[i][j] = dp[i-1][j-1]+1;  
  46.   
  47.                 }else dp[i][j] = -1;  
  48.             }   
  49.             else  
  50.             {  
  51.                 if(dp[i-1][j-1]!=-1 && input[i-1]==rule[j-1]){  
  52.                     dp[i][j] = dp[i-1][j-1]+1;  
  53.                 }else dp[i][j] = -1;  
  54.             }  
  55.         }  
  56.     }  
  57.   
  58.     int m = -1;//记录最大字符串长度   
  59.     int *ans = new int[len1];  
  60.     int count_ans = 0;//记录答案个数   
  61.     char *returnans = new char[len1+1];  
  62.     int count = 0;  
  63.     for(int i = 1;i<=len1;i++)  
  64.         if (dp[i][len2]>m){  
  65.             m = dp[i][len2];  
  66.             count_ans = 0;  
  67.             ans[count_ans++] = i-m;  
  68.         }else if(dp[i][len2]!=-1 &&dp[i][len2]==m){  
  69.             ans[count_ans++] = i-m;  
  70.         }  
  71.   
  72.         if (count_ans!=0)  
  73.         {      
  74.             int len = ans[0];  
  75.             for (int i = 0;i<m;i++)  
  76.             {  
  77.                 printf("%c",input[i+ans[0]]);  
  78.                 returnans[count++] = input[i+ans[0]];  
  79.             }  
  80.             for (int j = 1;j<count_ans;j++)  
  81.             {  
  82.                 printf(" ");  
  83.                 returnans[count++] = ' ';  
  84.                 len = ans[j];  
  85.                 for (int i = 0;i<m;i++)  
  86.                 {  
  87.                     printf("%c",input[i+ans[j]]);  
  88.                     returnans[count++] = input[i+ans[j]];  
  89.                 }  
  90.             }  
  91.             printf("\n");  
  92.             returnans[count++] = '\0';  
  93.         }  
  94.   
  95.         return returnans;  
  96. }  
//copyright@chpeih 2013/4/23
char* my_find(char  input[],   char rule[])
{
	//write your code here
	int len1,len2;
	for(len1 = 0;input[len1];len1++);
	for(len2 = 0;rule[len2];len2++);
	int MAXN = len1>len2?(len1+1):(len2+1);
	int  **dp;

	//dp[i][j]表示字符串1和字符串2分别以i j结尾匹配的最大长度
	//记录dp[i][j]是由之前那个节点推算过来  i*MAXN+j
	dp = new int *[len1+1];
	for (int i = 0;i<=len1;i++)
	{
		dp[i] = new int[len2+1];

	}

	dp[0][0] = 0;
	for(int i = 1;i<=len2;i++)
		dp[0][i] = -1;
	for(int i = 1;i<=len1;i++)
		dp[i][0] = 0;

	for (int i = 1;i<=len1;i++)
	{
		for (int j = 1;j<=len2;j++)
		{
			if(rule[j-1]=='*'){
				dp[i][j] = -1;
				if (dp[i-1][j-1]!=-1)
				{
					dp[i][j] = dp[i-1][j-1]+1;

				}
				if (dp[i-1][j]!=-1 && dp[i][j]<dp[i-1][j]+1)
				{
					dp[i][j] = dp[i-1][j]+1;

				}
			}else if (rule[j-1]=='?')
			{
				if(dp[i-1][j-1]!=-1){
					dp[i][j] = dp[i-1][j-1]+1;

				}else dp[i][j] = -1;
			} 
			else
			{
				if(dp[i-1][j-1]!=-1 && input[i-1]==rule[j-1]){
					dp[i][j] = dp[i-1][j-1]+1;
				}else dp[i][j] = -1;
			}
		}
	}

	int m = -1;//记录最大字符串长度
	int *ans = new int[len1];
	int count_ans = 0;//记录答案个数
	char *returnans = new char[len1+1];
	int count = 0;
	for(int i = 1;i<=len1;i++)
		if (dp[i][len2]>m){
			m = dp[i][len2];
			count_ans = 0;
			ans[count_ans++] = i-m;
		}else if(dp[i][len2]!=-1 &&dp[i][len2]==m){
			ans[count_ans++] = i-m;
		}

		if (count_ans!=0)
		{    
			int len = ans[0];
			for (int i = 0;i<m;i++)
			{
				printf("%c",input[i+ans[0]]);
				returnans[count++] = input[i+ans[0]];
			}
			for (int j = 1;j<count_ans;j++)
			{
				printf(" ");
				returnans[count++] = ' ';
				len = ans[j];
				for (int i = 0;i<m;i++)
				{
					printf("%c",input[i+ans[j]]);
					returnans[count++] = input[i+ans[j]];
				}
			}
			printf("\n");
			returnans[count++] = '\0';
		}

		return returnans;
}

     欢迎于本文评论下或hero上 show your code


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言中字符串*通配符匹配过程的示例代码: ```c #include <stdio.h> #include <string.h> int match(char *pattern, char *text) { // 如果 pattern 和 text 都为空,则匹配成功 if (*pattern == '\0' && *text == '\0') { return 1; } // 如果 pattern 为空但 text 不为空,则匹配失败 if (*pattern == '\0') { return 0; } // 如果 pattern 的第二个字符是 *,则有两种情况: if (*(pattern + 1) == '*') { // 1. * 匹配 0 个字符 if (match(pattern + 2, text)) { return 1; } // 2. * 匹配 1 个或多个字符 while (*text != '\0' && (*pattern == '.' || *pattern == *text)) { if (match(pattern + 2, text + 1)) { return 1; } text++; } return 0; } // 如果 pattern 的第二个字符不是 *,则只需匹配第一个字符是否相同 if (*text != '\0' && (*pattern == '.' || *pattern == *text)) { return match(pattern + 1, text + 1); } return 0; } int main() { char pattern[] = "a*b*c"; char text1[] = "abc"; char text2[] = "aabbcc"; char text3[] = "ac"; printf("%s\t%s\t%d\n", pattern, text1, match(pattern, text1)); printf("%s\t%s\t%d\n", pattern, text2, match(pattern, text2)); printf("%s\t%s\t%d\n", pattern, text3, match(pattern, text3)); return 0; } ``` 输出结果为: ``` a*b*c abc 1 a*b*c aabbcc 1 a*b*c ac 0 ``` 其中,函数 match 的参数 pattern 和 text 分别表示要匹配的模式和文本,函数返回值表示是否匹配成功。在函数中,使用递归的方式匹配字符串,考虑了模式中的通配符 *,并且实现了通配符 * 匹配 0 个、1 个或多个字符的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值