对于字符串A,其中绝对不含有字符’.’和’*’。再给定字符串B,其中可以含有’.’或’*’,’*’字符不能是B的首字符,并且任意两个’*’字符不相邻。exp中的’.’代表任何一个字符,B中的’*’表示’*’的前一个字符可以有0个或者多个。请写一个函数,判断A是否能被B匹配。
给定两个字符串A和B,同时给定两个串的长度lena和lenb,请返回一个bool值代表能否匹配。保证两串的长度均小于等于300。
测试样例:
"abcd",4,".*",2
返回:true
对于字符串A,其中绝对不含有字符’.’和’*’。再给定字符串B,其中可以含有’.’或’*’,’*’字符不能是B的首字符,并且任意两个’*’字符不相邻。exp中的’.’代表任何一个字符,B中的’*’表示’*’的前一个字符可以有0个或者多个。请写一个函数,判断A是否能被B匹配。
给定两个字符串A和B,同时给定两个串的长度lena和lenb,请返回一个bool值代表能否匹配。保证两串的长度均小于等于300。
"abcd",4,".*",2
返回:true
package alex.suda.dp; import java.util.Scanner; public class test8 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); String A = scanner.next(); int m = scanner.nextInt(); String B = scanner.next(); System.out.println(chkWildMatch(A, n, B, m)); } } public static boolean chkWildMatch(String A, int lena, String B, int lenb) { // d[i][j]表示A中的1~i位可以匹配B中的1~j位 boolean[][] d = new boolean[lena + 1][lenb + 1]; // 初始化 d[0][0] = true; for (int i = 1; i <= lena; i++) { for (int j = 1; j <= lenb; j++) { if (B.charAt(j - 1) == '*') { d[i][j] = d[i - 1][j] || d[i][j - 1]; } else if (B.charAt(j - 1) == '.') { d[i][j] = d[i - 1][j - 1]; } else { d[i][j] = d[i - 1][j - 1] && A.charAt(i - 1) == B.charAt(j - 1); } } } return d[lena][lenb]; } }
import java.util.*; public class WildMatch { public boolean chkWildMatch(String A, int lena, String B, int lenb) { boolean[][] dp = new boolean[lena + 1][lenb + 1]; dp[0][0] = true; for (int i = 1; i <= lena; i ++ ) { for (int j = 1; j <= lenb; j ++ ) { if(B.charAt(j - 1) == '.' || B.charAt(j - 1) == A.charAt(i - 1)) dp[i][j] = dp[i - 1][j - 1]; if(B.charAt(j - 1) == '*') dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; } } return dp[lena][lenb]; } }
class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { if (B[0] == '*') return false; vector<vector<bool> > dp(lenb + 1, vector<bool>(lena + 1, false)); dp[0][0] = true; for (int i = 0; i < lenb; i++) { if (B[i] == '*') { dp[i + 1][0] = dp[i - 1][0]; for (int j = 0; j < lena; j++) { dp[i + 1][j + 1] = dp[i][j + 1] || dp[i - 1][j + 1]; if (isEqual(A[j], B[i - 1])) dp[i + 1][j + 1] = dp[i + 1][j + 1] || dp[i + 1][j]; } } else { for (int j = 0; j < lena; j++) { if (isEqual(A[j], B[i])) { dp[i + 1][j + 1] = dp[i][j]; } } } } return dp[lenb][lena]; } inline bool isEqual(char a, char b) { if (a == b || b == '.') return true; else return false; } };
class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { // write code here int i=lena-1; int j=lenb-1; while(i>=0&&j>=0){ if(A[i]==B[j]||B[j]=='.'){ i--; j--; } else if(B[j]=='*'){ lenb=j; j--; } else { i=i-j+lenb-2; j=lenb-1; } } if(j<0) return 1; else return 0; } };
该题只要从后往前匹配就可以了,遇到‘.‘跳过,遇到’*‘分段。
//递归详解
import java.util.*;
public class WildMatch {
public boolean chkWildMatch(String A, int lena, String B, int lenb) {
// write code here
return isP(A,0,B,0);
}
//ia为A当前索引位置,ib为B当前索引位置,函数返回值为到当前位置是否匹配
//结束且结果为true或false
public boolean isP(String A,int ia,String B,int ib){
//当A匹配结束且B结束返回true
if(ia==A.length()&&ib==B.length())
return true;
//边界控制,超出返回false
if(ib>=B.length()||ia>=A.length())
return false;
//当A匹配结束但B还没匹配到结尾返回false
if((ia==A.length()&&ib!=B.length()))
return false;
//当A[ia]!=B[ib]且B[ib]!='.'时返回false
if(A.charAt(ia)!=B.charAt(ib)&&B.charAt(ib)!='.')
return false;
boolean isp = false;
//B的ib下一个是*时
if((ib+1<B.length())&&B.charAt(ib+1)=='*'){
//选用*的功能,ib索引位置不变,ia+1进行匹配
boolean is1 = isP(A,ia+1,B,ib);
//不选用*的功能,ib跳到'*'后一个位置ib+2,ia+1进行匹配
boolean is2 = isP(A,ia+1,B,ib+2);
isp = is1|is2;
}else{//下一个不是*时,直接进行下一个匹配
isp = isP(A,ia+1,B,ib+1);
}
return isp;
}
}
//递归有点多啊,不断调用自己往后匹配 class WildMatch { public: //flag 是看匹配了几次,因为只能匹配0或多次,不能1次 //nowa 是a匹配到哪一位了, nowb 是b匹配到哪一位了, b匹配完就结束 bool match(string A, int lena,int nowa, string B, int lenb,int nowb,int flag){ if(nowa <= lena && nowb == lenb) return true; if( nowa > lena || nowb > lenb ) return false; if(B[nowb] == '.'){ if(B[nowb+1] == '*'){ if(flag == 1){ //若之前匹配了一次,必须再匹配 return match(A,lena,nowa+1,B,lenb,nowb,flag+1) ; } else //匹配多一次,最后一次匹配,或匹配0次 return match(A,lena,nowa+1,B,lenb,nowb,flag+1) || match(A,lena,nowa,B,lenb,nowb+2,0) || match(A,lena,nowa+1,B,lenb,nowb+2,0) ;// 匹配多次 || 匹配0次 } else return match(A,lena,nowa+1,B,lenb,nowb+1,0); } else if( A[nowa] != B[nowb]) return false; else if( A[nowa] == B[nowb]) { //情况和“.”一样 if(B[nowb+1] == '*'){ if(flag == 1){ return match(A,lena,nowa+1,B,lenb,nowb,flag+1); } else return match(A,lena,nowa+1,B,lenb,nowb,flag+1) || match(A,lena,nowa,B,lenb,nowb+2,0) || match(A,lena,nowa+1,B,lenb,nowb+2,0) ;// 匹配多次 || 匹配0次 } else return match(A,lena,nowa+1,B,lenb,nowb+1,0); } return false; } bool chkWildMatch(string A, int lena, string B, int lenb) { // write code here return match(A,lena,0,B,lenb,0,0); } };
看了上边好多代码都是有bug,可以测试样例: 样例一: "" , 0, ".*", 2 应该输出true,绝多数代码输出false 样例二: "aaaaabcd", 8, "a*abcd" 应该输出true class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { // write code here int **dp=new int*[lena+1]; for(int i=0; i<=lena; ++i) dp[i]=new int[lenb+1]; dp[0][0]=true; for(int i=1; i<=lena; ++i) dp[i][0]=false; for(int i=1; i<=lenb; ++i) dp[0][i]=(i>=2 && B[i-1]=='*' && dp[0][i-2]); for(int i=1; i<=lena; ++i) for(int j=1; j<=lenb; ++j){ int ii=i-1; int jj=j-1; if(B[jj]=='*') dp[i][j]=dp[i][j-2] || ((dp[i-1][j] || (dp[i-1][j-2])&&(B[jj-1]=='.' || B[jj-1]==A[ii])); else if(B[jj]=='.') dp[i][j]=dp[i-1][j-1]; else dp[i][j]=dp[i-1][j-1] && A[ii]==B[jj]; } int ans=dp[lena][lenb]; for(int i=0; i<=lena; ++i) delete []dp[i]; delete []dp; return ans; } };
/*
*@author snow
*@time 2016-08-13 16:16:28
* *学java的,题比较简单,所以第一次尝试用C++写程序
*算法复杂度O(n);姑且认为n=max(lena,lenb);
*/
class WildMatch {
public:
bool chkWildMatch(string A, int lena, string B, int lenb) {
// write code here
if(B.find(".*")<B.length()){
return true;
}
int j = 0;
for(int i=0;i<lenb;i++){
if(j>=lena){
return true;
}
if(A[j] == B[i] || B[i] == '.'){
j++;
}else if(B[i] == '*'){
if(A[j] == B[i-1]){
j++;
i--;
}else if(A[j] == B[i+1]){
j++;
i++;
}
}
}
if(j>=lena){
return true;
}else
return false;
}
};
class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { // write code here int count = 0; B += " "; for(int i = 1; i <= lenb; i++) { if(B[i-1] != '*') { if(B[i] == '*')//处理 字母+*情况 { for(int j = 0; j < lena; j++) { if(B[i-1] == '.') return true; if(B[i-1] == A[j]) count++; } } else//处理 只有单次字母情况 { for(int j = 0; j < lena; j++) { if(B[i-1] == A[j]) { count++; break; } } } } } return count >= lena; } };
class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { if(B[0]=='*') return false; vector<vector<bool> > dp(lenb+1, vector<bool>(lena+1,false)); dp[0][0] = true; for(int i=0;i<lenb;i++) { if(B[i] == '*') { dp[i+1][0] = dp[i-1][0]; for(int j=0;j<lena;j++) { dp[i+1][j+1] = dp[i][j+1] || dp[i-1][j+1]; if(A[j]==B[i-1] || B[i-1]=='.') dp[i+1][j+1] = dp[i+1][j+1] || dp[i+1][j]; } }else{ for(int j=0;j<lena;j++) if(A[j]==B[i] || B[i]=='.') dp[i+1][j+1] = dp[i][j]; } } return dp[lenb][lena]; } };
//检查正则表达式的匹配 //递归 class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { // write code here return isMatch(A.c_str(), B.c_str()); } private: bool isMatch(const char *a, const char *b) { if (*b == '\0') return *a == '\0'; //如果字母b后面不是'*',那么b必须匹配一个,否则FALSE if (*(b + 1) != '*') { // 注意:虽然b为'.'时代表任意一个字符,但是不能匹配 '\0' if (*a == *b || *b == '.' && *a != '\0') { return isMatch(a + 1, b + 1); } else { return false; } } else { //字母b后面是'*'' //当字母b匹配或者b为'.'时,跳过b和'*'再进行匹配 while (*a == *b || (*b == '.' && *a != '\0')) { if (isMatch(a, b + 2)) { return true; } a++; } return isMatch(a, b + 2); } } };
}
bool chkWildMatch(string A, int lena, string B, int lenb) { //设置初始值 bool** temp = new bool*[lenb + 1]; for (int i=0; i<lenb+1; i++) { temp[i] = new bool[lena + 1]; temp[i][0] = false; } for (int i=0; i<lena+1; i++) { temp[0][i] = false; } temp[0][0] = true; /* *号:d[i][j]=d[i][j-1] || d[i-1][j] 非*号:d[i][j]=d[i-1][j-1] && m(i,j) 其中:m(i,j) = (b[i]== '.' || b[i]==a[i]) */ for (int i=1; i<=lenb; i++) { if(B.at(i-1) == '*'){ for (int j=1; j<=lena; j++){ temp[i][j] = temp[i][j-1] || temp[i-1][j]; } }else{ for (int j=1; j<=lena; j++) { temp[i][j] = temp[i-1][j-1] && (B.at(i-1) == '.' || A.at(j-1) == B.at(i-1)); } } } return temp[lenb][lena]; }
class WildMatch { public: bool chkWildMatch(string A, int lena, string B, int lenb) { const char * p1 = A.c_str(); const char * p2 = B.c_str(); return match(p2, p1); } int matchstar(int c,const char *regexp,const char *text) { do {// a * matches zero or more instances if (matchhere(regexp, text)) return 1; } while (*text != '\0' && (*text++ == c || c == '.')); return 0; } int matchhere( const char *regexp, const char *text) { if (regexp[0] == '\0') return 1; if (regexp[1] == '*') return matchstar(regexp[0], regexp + 2, text); if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0'; if (*text != '\0' && (regexp[0] == '.' || regexp[0] == *text)) return matchhere(regexp + 1, text + 1); return 0; } int match(const char *regexp,const char *text) { if (regexp[0] == '^') return matchhere(regexp + 1, text); do {// must look even if string is empty if (matchhere(regexp, text)) return 1; } while (*text++ != '\0'); return 0; } };
import java.util.*; public class WildMatch { public boolean chkWildMatch(String A, int lena, String B, int lenb) { // write code here char[] SA=A.toCharArray(); char[] SB=B.toCharArray(); return chkWildMatchHelper(SA,0,SB,0); } public boolean chkWildMatchHelper(char[] SA,int ai,char[] SB,int bi){ if(bi==SB.length) return ai==SA.length; if(bi+1==SB.length || SB[bi+1]!='*'){ if(ai!=SA.length && (SA[ai]==SB[bi] || SB[bi]=='.')) return chkWildMatchHelper(SA,ai+1,SB,bi+1); else return false; } else{ while(ai!=SA.length && (SA[ai]==SB[bi] || SB[bi]=='.')){ if(chkWildMatchHelper(SA,ai,SB,bi+2)) return true; ai++; } return chkWildMatchHelper(SA,ai,SB,bi+2); } } }