下面的方法接受字符串和模式,如果彼此匹配则返回 true 。 A'。'匹配1个字符和一个' *'匹配0或更多(例如expMatch("abc", "a.c")
应返回 true )。我添加了一堆打印语句来查看我出错的地方,即使str.length() == 1
,似乎也会跳过if语句。
我用System.out.println(expMatch("abc", "a*c"));
以下是代码:
public static boolean expMatch(String str, String pat)
{
if (str.charAt(0) == pat.charAt(0) || pat.charAt(0) == '.')
{
System.out.println("in if");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
System.out.println(str.length());
if (str.length() == 1)
return true;
expMatch(str.substring(1), pat.substring(1));
}
else if (pat.charAt(0) == '*')
{
System.out.println("in else");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
if (str.length() == 1)
return true;
if (str.charAt(0) == pat.charAt(1)) //val of * = 0
expMatch(str, pat.substring(1));
else if (str.charAt(1) ==pat.charAt(1))
expMatch(str.substring(1), pat.substring(1));
}
return false;
}
,输出为:
in if
a
a
3
in else
b
*
in if
c
c
1
false
即使长度为1,它也会跳过if?知道为什么吗? 附:我没有找到解决方案,只是为什么要跳过if语句。
答案 0 :(得分:6)
总是从最后的方法返回false。您以递归方式调用expmatch但从不使用返回值。代码进入第一个if,recurses(因为length不是1)并且在返回时将转到返回false的最终return语句。
答案 1 :(得分:4)
您需要在expMatch()调用之前添加一个返回值 - 因为false
来自您的最后一行return false;
这是怎么回事:
答案 2 :(得分:3)
即使您应用其他人建议的修补程序,您的方法在逻辑上也是不正确的。试试这个测试用例:
System.out.println(expMatch("abddddc", "a*c"));
这是因为当您在模式中遇到*
时,您无法知道搜索字符串中有多少字符“吃”。
至少可以说,你需要一个循环,而不仅仅是if
。让我试着为你修复它(不确定它是否可能,不确定你是否总是知道要采取哪条路径,我的意思是你的递归)。想一想更多。这是另一个令人不快的测试用例:
System.out.println(expMatch("adddcac", "a*c"));
// the * needs to eat dddca (despite the c present in dddca),
// it should not stop recursing there at that c
我认为你需要在这里进行一些完整的搜索
只有if
或while
循环不够好。
编辑:这是一个固定版本,有一堆讨厌的测试。我认为这被称为非线性递归(因为它不是你尝试的单一路径)。关于那个词,不是100%肯定。
public class Test055 {
public static void main(String[] args) {
// System.out.println(expMatch("abddddc", "a*c"));
System.out.println(expMatch("adcax", "a*c"));
System.out.println(expMatch("adcax", "a*c*"));
System.out.println(expMatch("adcacm", "*"));
System.out.println(expMatch("adcacmmm", "a*c"));
System.out.println(expMatch("adcacmmmc", "a*c"));
System.out.println(expMatch("adcac", "a*c"));
System.out.println(expMatch("adcacxb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c*b"));
}
public static boolean expMatch(String str, String pat)
{
// System.out.println("=====================");
// System.out.println("str=" + str);
// System.out.println("pat=" + pat);
if (pat.length() == 0 && str.length() > 0) {
return false;
} else if (pat.length() == 0 && str.length() == 0) {
return true;
} else if (pat.charAt(0) == '.'){
return str.length() >= 1 && expMatch(str.substring(1), pat.substring(1));
}else if (pat.charAt(0) != '*'){
return str.length() >= 1 && pat.charAt(0) == str.charAt(0) && expMatch(str.substring(1), pat.substring(1));
}else{
// Now let's handle the tricky part
// (1) Look for the 1st non-star in pattern
int k=-1;
char ch = ' ';
for (int i=0; i<pat.length(); i++){
if (pat.charAt(i) != '*'){
k = i;
ch = pat.charAt(k);
break;
}
}
if (k==-1){
// (2A) only stars found in pattern, OK, any str matches that
return true;
}else{
// (2B) do full search now checking all
// possible candidate chars in str that
// match the char ch from pattern
for (int i=0; i<str.length(); i++){
if (str.charAt(i)==ch){
boolean b = expMatch(str.substring(i+1), pat.substring(k+1));
if (b) return true;
}
}
return false;
}
}
}
}