输入包含两行,两个字符串,分别代表str和exp。
如果str是能被exp匹配,请输出“YES”,否则输出“NO”。
abc abc
YES
abcd .*
YES
时间复杂度,额外空间复杂度,(n为字符串str长度,m为字符串exp长度)
#include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> // 初始化一个动态大小的矩阵 #define INIT_MATRIX(TYPE, PTR, COL, ROW) \ (PTR) = (TYPE **) malloc(sizeof(TYPE *) * (COL));\ for (int i = 0; i < (COL); i++)\ (PTR)[i] = (TYPE *) calloc((ROW), sizeof(TYPE)) // 释放一个动态大小的矩阵 #define FREE_MATRIX(PTR, COL) \ for (int i = 0; i < (COL); i++) {\ free((PTR)[i]);\ }\ free((PTR)) #define MAXLEN 301 bool is_valid(char *str, char *exp); bool **get_dp(const char *str, const char *exp, int str_len, int exp_len); int main(void) { char str[MAXLEN], exp[MAXLEN]; scanf("%s%s", str, exp); if (!is_valid(str, exp)) { printf("NO\n"); return 0; } int str_len = (int) strlen(str); int exp_len = (int) strlen(exp); bool **dp = get_dp(str, exp, str_len, exp_len); for (int i = str_len - 1; i >= 0; i--) { for (int j = exp_len - 2; j >= 0; j--) { if (exp[j + 1] != '*') { dp[i][j] = (exp[j] == '.' || str[i] == exp[j]) && dp[i + 1][j + 1]; } else { int si = i; while (si != str_len && (exp[j] == '.' || str[si] == exp[j])) { if (dp[si][j + 2]) { dp[i][j] = true; break; } si++; } if (!dp[i][j]) { dp[i][j] = dp[si][j + 2]; } } } } printf("%s\n", dp[0][0] ? "YES" : "NO"); FREE_MATRIX(dp, strlen(str)); return 0; } bool is_valid(char *str, char *exp) { for (int i = 0; i < strlen(str); i++) { if (str[i] == '.' || str[i] == '*') { return false; } } for (int i = 0; i < strlen(exp); i++) { if (str[i] == '*' && (i == 0 || str[i - 1] == '*')) { return false; } } return true; } bool **get_dp(const char *str, const char *exp, int str_len, int exp_len) { bool **dp; INIT_MATRIX(bool, dp, str_len + 1, exp_len + 1); dp[str_len][exp_len] = true; for (int j = exp_len - 2; j >= 0; j -= 2) { dp[str_len][j] = exp[j + 1] == '*'; if (!dp[str_len][j]) { break; } } dp[str_len - 1][exp_len - 1] = exp[exp_len - 1] == '.' || str[str_len - 1] == exp[exp_len - 1]; return dp; }
递归解法
import java.util.*; public class Main { //isValid public static boolean isValid(char[] s, char[] e) { for(int i = 1; i < e.length; i++) { if (e[i] == '*' && e[i - 1] == '*') return false; } return true; } public static boolean judge(char[] s, char[] e, int si, int ei) { if (ei == e.length) { return si == s.length; } if (ei + 1 == e.length || e[ei + 1] != '*') { return si != s.length && (e[ei] == s[si] || e[ei] == '.') && judge(s, e, si + 1, ei + 1); } while (si != s.length && (e[ei] == s[si] || e[ei] == '.')) { if (judge(s, e, si, ei + 2)) { return true; } si ++; } return judge(s, e, si, ei + 2); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); char[] s = sc.nextLine().toCharArray(); char[] e = sc.nextLine().toCharArray(); sc.close(); if (!isValid(s, e)) { System.out.println("NO"); return; } if (!judge(s, e, 0, 0)) { System.out.println("NO"); } else { System.out.println("YES"); } } }
动态规划解法
import java.util.*; public class Main { public static boolean isValid(char[] s, char[] e) { for (int i = 0; i < s.length; i++) { if (s[i] == '*' || s[i] == '.') { return false; } } for (int i = 0; i < e.length; i++) { if (e[i] == '*' && (i == 0 || e[i - 1] == '*')) { return false; } } return true; } public static boolean isMatchDP(String str, String exp) { if (str == null || exp == null) { return false; } char[] s = str.toCharArray(); char[] e = exp.toCharArray(); if (!isValid(s, e)) { return false; } boolean[][] dp = initDPMap(s, e); for (int i = s.length - 1; i > -1; i--) { for (int j = e.length - 2; j > -1; j--) { if(e[j + 1] != '*') { dp[i][j] = (s[i] == e[j] || e[j] == '.') && dp[i + 1][j + 1]; } else { int si = i; while (si != s.length && (s[si] == e[j] || e[j] == '.')) { if (dp[si][j + 2]) { dp[i][j] = true; break; } si++; } if (dp[i][j] != true) { dp[i][j] = dp[si][j + 2]; } } } } return dp[0][0]; } public static boolean[][] initDPMap(char[] s, char[] e) { int slen = s.length; int elen = e.length; boolean[][] dp = new boolean[slen + 1][elen + 1]; dp[slen][elen] = true; for (int j = elen - 2; j > -1; j -= 2) { if (e[j] != '*' && e[j + 1] == '*') { dp[slen][j] = true; } else { break; } } if (slen > 0 && elen > 0) { if ((e[elen - 1] == '.' || s[slen - 1] == e[elen - 1])) { dp[slen - 1][elen - 1] = true; } } return dp; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.nextLine(); String exp = sc.nextLine(); if (isMatchDP(str, exp)) { System.out.println("YES"); } else { System.out.println("NO"); } } }
import java.util.*; public class Main { public static void main (String[] args) { Scanner sc = new Scanner(System.in); String s1 = sc.nextLine(); String s2 = sc.nextLine(); if (isMatch(s1, s2)) System.out.println("YES"); else System.out.println("NO"); sc.close(); } public static boolean isValid(String s1, String s2) { if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) return false; if (s1 == null && s2 == null) return true; char[] str1 = s1.toCharArray(); char[] str2 = s2.toCharArray(); for (int i = 0; i < str1.length; i++) { if (str1[i] == '*' || str1[i] == '.') return false; } for (int i = 0; i < str2.length; i++) { if (str2[i] == '*' && (i == 0 || str2[i-1] == '*')) return false; } return true; } public static boolean isMatch(String s1, String s2) { if (!isValid(s1, s2)) return false; char[] str = s1.toCharArray(); char[] exp = s2.toCharArray(); return getDP(str, exp); } //str[si...slen]是否能被exp[ei...elen]匹配, 以exp以及ei为判断基准 public static boolean process(char[] str, char[] exp, int si, int ei) { //当exp走完时,若si也走到头了,空只能匹配空 if (ei == exp.length) return si == str.length; //要么遍历到exp最后一位,要么后面不是* if(ei == exp.length-1 || exp[ei+1] != '*') { //如果str都遍历完了自然false;如果当前位置不等或后续无法匹配,false return si != str.length && process(str, exp, si+1, ei+1) && (str[si] == exp[ei] || exp[ei] == '.'); } //此时exp肯定没到最后且ei+1位置为'*', 比如aaaaXXX与a*XXX, 只要能出来匹配成功一对,即可返回true while (si != str.length && (str[si] == exp[ei] || exp[ei] == '.')) { if (process(str, exp, si, ei+2)) return true; si++; } //说明此时尽管exp[ei+1] == '*', 但当前str[si] 根本无法匹配出来 exp[ei],那么 //只能让exp[ei]已经'*'为空,继续往后查吧 return process(str, exp, si, ei+2); } //动态规划 public static boolean getDP(char[] str, char[] exp) { //dp[i][j]表示str从[i...len-1]与exp[j...len-1]是否可以匹配 boolean[][] dp = new boolean[str.length+1][exp.length+1]; dp[str.length][exp.length] = true; for (int i = exp.length-2; i > -1; i--) { if (exp[i] != '*' && exp[i+1] == '*') dp[str.length][i] = true; else break; } if (str.length > 0 && exp.length > 0) dp[str.length-1][exp.length-1] = exp[exp.length-1] == str[str.length-1] || exp[exp.length-1] == '.'; for (int i = str.length-1; i > -1; i--) { for (int j = exp.length-2; j > -1; j--) { if (exp[j+1] != '*') { dp[i][j] = (str[i] == exp[j] || exp[j] == '.') && dp[i+1][j+1]; } else { int si = i; while (si < str.length && (str[si] == exp[j] || exp[j] == '.')) { if (dp[si][j+2]) { dp[i][j] = true; break; } si++; } if(!dp[i][j]) dp[i][j] = dp[si][j+2]; } } } return dp[0][0]; } }
import java.io.*; public class Main{ public static void main(String[] args) throws IOException{ BufferedReader sc = new BufferedReader(new InputStreamReader(System.in)); String str = sc.readLine(); String exp = sc.readLine(); char[] ch1= str.toCharArray(); char[] ch2 = exp.toCharArray(); boolean result = isMatch(ch1,ch2); if(result){ System.out.print("YES"); } else{ System.out.print("NO"); } } public static boolean isValid(char[] ch1,char[] ch2){ for(int i = 0;i<ch1.length;i++){ if(ch1[i]=='.'||ch1[i]=='*'){ return false; } } for(int i = 0; i< ch2.length;i++){ if(ch2[i]=='*'&&(i==0||ch2[i-1]=='*')){ return false; } } return true; } public static boolean isMatch(char[] s,char[] e){ if(s==null||e==null){ return false; } return isValid(s,e) ? process(s,e,0,0): false; } public static boolean process(char[] s, char[] e, int si ,int ei){ if(ei==e.length){ return s.length ==si; } if(ei+1==e.length||e[ei+1]!='*'){ return si!=s.length &&(s[si]==e[ei]||e[ei]=='.') && process(s,e,si+1,ei+1); } while(si!=s.length && (e[ei]==s[si]||e[ei]=='.')){ if(process(s,e,si,ei+2)){ return true; } si++; } return process(s,e,si,ei+2); } }
#include<cstdio> (802)#include<cstring> #include<algorithm> using namespace std; char str1[310],str2[310]; int dp[310][310]; int main(){ while(~scanf("%s %s",str1+1,str2+1)){ fill(dp[0],dp[0]+310*310,0); int len1=strlen(str1+1); int len2=strlen(str2+1); int flag=0; for(int i=1;i<=len2;++i){ if(str2[i]=='*'&&(str2[i+1]=='*'||i==1)){ printf("NO\n"); flag=1; break; } } if(flag==1) return 0; for(int i=0;i<=len1;++i){ for(int j=0;j<=len2;++j){ if(i==0&&j==0) { dp[i][j]=1; continue; } if(i>0&&j==0) { dp[i][j]=0; continue; } if(str2[j]!='*'){ if(i==0) continue; if(str1[i]==str2[j]||str2[j]=='.') { dp[i][j]=dp[i-1][j-1]; } } else{ if(i==0||str1[i]!=str2[j-1]&&str2[j-1]!='.') dp[i][j]=dp[i][j-2]; else dp[i][j]=dp[i][j-2]||dp[i-1][j-2]||dp[i-1][j]; } } } if(dp[len1][len2]==1) printf("YES\n"); else{ printf("NO\n"); } } return 0; }
strs=input().strip() exp=input().strip() n,m=len(strs),len(exp) dp=[[False]*(m+1) for _ in range(n+1)] dp[0][0]=True for i in range(1,m): if exp[i]=='.': dp[0][i+1]=dp[0][i] elif exp[i]=='*': dp[0][i+1]=dp[0][i-1] else: dp[0][i+1]=False for i in range(n): dp[i+1][0]=False for j in range(m): if strs[i]==exp[j]&nbs***bsp;exp[j]=='.': dp[i+1][j+1]=dp[i][j] elif exp[j]=='*': if exp[j-1]=='.'&nbs***bsp;exp[j-1]==strs[i]: dp[i+1][j+1]=dp[i][j+1]&nbs***bsp;dp[i-1][j-1] else: dp[i+1][j+1]=dp[i+1][j-1] if dp[n][m]: print('YES') else: print('NO')
#include <iostream> #include <cstring> using namespace std; int main(){ string str,exp; cin>>str; cin>>exp; int flag = 0; for(int i=0;i<str.size();i++){ //如果str中有'.' 和 '*' if(str[i]=='.' || str[i]=='*'){ flag = 1; break; } } if(exp[0]=='*'){ // 如果exp的首字母为'*' flag = 1; } int num=0; for(int i=0;i<exp.size();i++){ // 如果exp有两个连续的'*' if(exp[i]=='*' && num == 1){ flag = 1; break; } else if(exp[i] == '*' && num == 0){ num = 1; } else{ num = 0; } } int j=0; if(flag==1){ // 如果flag为1 cout<<"NO"; } else{ for(int i=0;i<str.size();i++){ if(j<=exp.size()-1){ // 判断exp是否已经匹配完 if((exp[j] == '*' && exp[j-1] == str[i]) || (exp[j] == '*' && exp[j-1] == '.')){ if((exp[j] == '*' && exp[j-1] == str[i] && exp[j+1] == str[i]) || exp[j] == '*' && exp[j-1] == str[i] && exp[j+1] =='.') j++; continue; } else if(exp[j] == '*' && exp[j-1] != str[i]){ j++; if(j<=exp.size()-1){ if(exp[j] == str[i] || exp[j] == '.') j++; else{ cout<<"NO"; flag = 1; break; } } else{ cout<<"NO"; flag = 1; break; } } else if(str[i] == exp[j] || exp[j] == '.'){ j++; } else{ cout<<"NO"; flag = 1; break; } } } if(flag != 1) cout<<"YES"; } return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String s = scanner.next(); String exp = scanner.next(); System.out.println(solution(s, exp)); } private static String solution(String s, String exp) { if (!checkValid(exp)) return "NO"; int i = 0, j = 0; while (i < s.length() && j < exp.length()) { if (exp.charAt(j) == '.') { i++; j++; } else if (exp.charAt(j) == '*') { //匹配前一个 if (j - 1 >= 0) { //可以匹配 if (exp.charAt(j - 1) == s.charAt(i) || exp.charAt(j - 1) == '.') { while (i < s.length() && (exp.charAt(j - 1) == s.charAt(i) || exp.charAt(j - 1) == '.')) { i++; } //匹配完了 if (i == s.length()) return "YES"; else { //未匹配完,正则向前移动 j++; } } else { //匹配不了,只能匹配0次,正则向前移动 j++; } } } else { //直接比较字母 if (s.charAt(i) != exp.charAt(j)) return "NO"; i++; j++; } } if (i == s.length() && j == exp.length()) return "YES"; return "NO"; } public static boolean checkValid(String exp) { if (exp==null||exp.length()==0) return false; if (exp.charAt(0) == '*') return false; for (int i = 0; i < exp.length(); i++) { if (i + 1 < exp.length() && exp.charAt(i) == '*'&& exp.charAt(i+1)=='*') { return false; } } return true; } }