对于字符串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);
}
}
}
B仅由'.'和''组成,所以,只考虑'.'和''的个数就可以了。
class WildMatch:
def chkWildMatch(self, A, lena, B, lenb):
dotcount = B.count('.')
starcount = B.count('*')
if starcount == 0: # 如果没有*,则.的个数必须和lena相同才返回Ture,否则返回False
if dotcount == lena:
return True
else:
return False
else: # 如果有*,因为*可以匹配0或多个,所以只需要(dotcount - starcount) <= lena 就返回Ture,否则返回False
if (dotcount - starcount) <= lena:
return True
else:
return False