题意:
方法一:
递归
思路:暴力枚举。
规则如下图所示:
#include <bits/stdc++.h> using namespace std; string s1,s2; int len1,len2; //递归 bool f(int x,int y){ if(x>=len1&&y>=len2){//成功匹配 return true; } if(x>=len1||y>=len2) return false; if(s1[x]=='*'){ int i=x; while(i<len1&&s1[i]==s1[i+1]){//多个连续的*,只取最后一个*匹配 i++; } if(f(i+1,y))//匹配0个字符 return true; for(int j=y;j<len2;j++){//匹配至少一个字符 if(!isalpha(s2[j])&&!isdigit(s2[j])){//*只能匹配英文字母和数字0到9 break; } if(f(i+1,j+1)) return true; } }else if(s1[x]=='?'){ if(!isalpha(s2[y])&&!isdigit(s2[y]))//?只能匹配英文字母和数字0到9 return false; if(f(x+1,y+1)) return true; }else{ if(s1[x]==s2[y])//相等,则递归下去 if(f(x+1,y+1)) return true; else return false; } return false; } int main(){ while(cin >> s1 >> s2){ len1=s1.size(),len2=s2.size(); for(int i=0;i<len1;i++){//转化成大写 if(s1[i]>='a'&&s1[i]<='z'){ s1[i]-=32; } } for(int i=0;i<len2;i++){//转化成大写 if(s2[i]>='a'&&s2[i]<='z'){ s2[i]-=32; } } if(f(0,0))//递归 cout << "true\n"; else cout << "false\n"; } return 0; }
时间复杂度:空间复杂度:
方法二:
动态规划
思路:动态规划。
dp[i][j]表示前 i 个通配符字符串和前 j 个匹配字符串是否匹配。
规则:
当通配符是 * :可以选择不匹配或匹配,dp[i][j]=dp[i-1][j] || dp[i][j-1];
当通配符是 ? :只有匹配字符是字母或数字时,可以选择匹配,dp[i][j]=dp[i-1][j-1];
当其他情况 :只有通配符与匹配字符相等时,可以选择匹配,dp[i][j]=dp[i-1][j-1]。
#include <bits/stdc++.h> using namespace std; string s1,s2; int len1,len2; int dp[105][105]; int main(){ while(cin >> s1 >> s2){ len1=s1.size(),len2=s2.size(); for(int i=0;i<len1;i++){//转化成大写 if(s1[i]>='a'&&s1[i]<='z'){ s1[i]-=32; } } for(int i=0;i<len2;i++){//转化成大写 if(s2[i]>='a'&&s2[i]<='z'){ s2[i]-=32; } } memset(dp,0,sizeof(dp)); //动态规划 dp[0][0]=1;//初始化 for(int i=1;i<=len1;i++) dp[i][0]=dp[i-1][0]&&(s1[i-1]=='*'); for(int i=1;i<=len1;i++){ for(int j=1;j<=len2;j++){ if(s1[i-1]=='*'){//用*匹配 dp[i][j]=dp[i-1][j]||dp[i][j-1]; }else if(s1[i-1]=='?'&&(isdigit(s2[j-1])||isalpha(s2[j-1]))){//用?匹配 dp[i][j]=dp[i-1][j-1]; }else if(s1[i-1]==s2[j-1]){//其他情况 dp[i][j]=dp[i-1][j-1]; } } } if(dp[len1][len2])//判断结果 cout << "true\n"; else cout << "false\n"; } return 0; }
时间复杂度:空间复杂度: