我有一份我无法弄清楚的家庭作业。我必须编写一个静态方法匹配(String x,String y),它返回一个布尔值,表示字符串x和字符串y是否匹配。匹配过程应该允许“通配符”,例如“@”字符,它将与任何单个字符匹配,“*”字符将匹配任何类型的0或更多字符。我不允许使用任何循环,我必须使用递归。 到目前为止我写的是......
public class CompareStrings {
public static boolean match(String x, String y) {
if (x.length() <= 1 && y.length() <= 1) {
if (x.equals("*") || y.equals("*")) {
return true;
}
if ((x.length() == 1 && y.length() == 1) && (x.equals("@") || y.equals("@"))) {
return true;
}
return x.equals(y);
}
String x1 = "";
String x2 = "";
String y1 = "";
String y2 = "";
if (x.length() == 0 && y.charAt(0) == '*') {
y2 = y.substring(1, y.length());
}
if (y.length() == 0 && x.charAt(0) == '*') {
x2 = x.substring(1, x.length());
}
if (x.length() > 1 && y.length() > 1) {
if (x.length() != y.length() && !x.contains("*") && !y.contains("*")) {
return false;
}
if (x.charAt(0) == '*') {
x1 = "*";
x2 = x.substring(1, x.length());
y1 = "*";
y2 = y.substring(y.length()-x2.length(), y.length());
}
else if (y.charAt(0) == '*') {
y1 = "*";
y2 = y.substring(1, y.length());
x1 = "*";
x2 = x.substring(x.length()-y2.length(), x.length());
}
else {
x1 = x.substring(0, 1);
x2 = x.substring(1, x.length());
y1 = y.substring(0, 1);
y2 = y.substring(1, y.length());
}
}
return match(x1, y1) && match(x2, y2);
}
public static void main(String[] args) {
System.out.println(match("hello", "hello.") + " 1 false"); // should return false
System.out.println(match("hello", "jello") + " 2 false"); // should return false
System.out.println(match("hello", "h@llo") + " 3 true"); // should return true
System.out.println(match("hello", "h@@@@") + " 4 true"); // should return true
System.out.println(match("hello", "h*") + " 5 true"); // should return true
System.out.println(match("hello", "*l*") + " 6 true"); // should return true
System.out.println(match("anyString", "*") + " 7 true"); // should return true
System.out.println(match("help", "h@@@@") + " 8 false"); // should return false
System.out.println(match("help", "h*") + " 9 true"); // should return true
System.out.println(match("help", "*l*") + " 10 true"); // should return true
System.out.println(match("help", "*l*p") + " 11 true"); // should return true
System.out.println(match("help", "h@llo") + " 12 false"); // should return false
System.out.println(match("", "*") + " 13 true"); // should return true
System.out.println(match("", "***") + " 14 true"); // should return true
System.out.println(match("", "@") + " 15 false"); // should return false
System.out.println(match("", "") + " 16 true"); // should return true
}
}
主要方法是作业给出的测试程序。我意识到我的代码有点凌乱 - 我有点争吵 - 但我似乎可以让它的大部分工作。唯一没有返回正确值的示例是数字11.当它应该为真时我得到错误。我认为这种情况发生的原因是因为字符串y以''开头,我的方法所做的就是将x和y字符串分成最后3个字符,即使第一个''在y中应该代表2个字符。如何才能使这样的案例返回匹配?
答案 0 :(得分:1)
基本上你需要理解递归的概念(这是你作业的目标)。递归的工作方式是每次函数调用自身时,当前执行(变量/执行信息)进入堆栈并在那里休眠直到新的调用结束。
为了解决你提到的问题,让我们举一个简单的例子,你好和h @ llo。解决问题的基本方法是一次又一次地匹配服务调用,直到
找到完美匹配 - 返回true
发现失败情况 - 返回错误
如果没有2以上,匹配就会将自己的一个字符小于上一个字符
像
这样的东西致电1:你好&amp; h @ llo //再次呼叫匹配并将呼叫移动到堆栈,等待回复
致电2:ello&amp; @llo //匹配特殊字符
调用3:llo和llo //完美匹配返回true以调用2
返回呼叫2:从prv呼叫收到true并返回呼叫1
返回调用1:收到true并返回main。
一旦理解了递归堆栈的概念,解决这个问题就很简单了
您的最终匹配方法看起来像
public static boolean match(String x, String y) {
//if both are empty
if(x.length()==0 && y.length()==0) return true;
//if one is empty
if(x.length()==0 )
{
if(y.charAt(0)!='*')
return false;
if(y.length()!=1)
//border line case
return match(x,y.substring(1));
else
return true;
}
if(y.length()==0 )
{
if(x.charAt(0)!='*')
return false;
if(x.length()!=1)
//border line case
return match(y,x.substring(1));
else
return true;
}
//Base case
if(x.equals(y) || x.equals("*") || y.equals("*"))
{
return true;//we are done as strings are equal
}
//we are here that means strings are not equal yet
if(x.charAt(0)=='@' || y.charAt(0)=='@' ||x.charAt(0)==y.charAt(0))
{
if(x.length()==1 && y.length()==1) return true;//this was the last character
if(x.length()>1 && y.length()>1)
{
//we have single char wild card or char 0 equal, lets remove the char at 0th location and check again
return (match(x.substring(1),y.substring(1)));
}
}
if(x.charAt(0)=='*')
{
//this is interesting now, we will need to skip 0..n number of characters till we find matching pattern
//case 0 chars: he*llo and hello
if(match(x.substring(1),y)==true)
{
return true;
}
else if (match(x.substring(1),y.substring(1))==true)
{
//case 1: he*lo and hello
return true;
}
else
{
//case n chars: h*o and hello
return (match(x, y.substring(1)));
}
}
if(y.charAt(0)=='*')
{
//this is interesting now, we will need to skip 0..n number of characters till we find matching pattern
//case 0 chars: he*llo and hello
if(match(y.substring(1),x)==true)
{
return true;
}
else if (match(x.substring(1),y.substring(1))==true)
{
//case 1: he*lo and hello
return true;
}
else
{
//case n chars: h*o and hello
return (match(y, x.substring(1)));
}
}
//nothing worked out
return false;
}
答案 1 :(得分:0)
本着recursion
(你的一个标签)而不是Java的精神,这里有一个Scheme实现,可以让你的所有测试用例都正确。
(define (match s1 s2) ; assumes s1 = string, s2 = pattern
(let matching ((l1 (string->list s1)) (l2 (string->list s2)))
(if (null? l1)
(or (null? l2) (eq? (car l2) #\*)) ; every #\*
(let ((c1 (car l1))
(c2 (car l2)))
(or (and (or (eq? c2 c1)
(eq? c2 #\@))
(matching (cdr l1) (cdr l2))) ; take one char from l1 and l2
(and (eq? c2 #\*)
(matching (cdr l1) l2))))))) ; take one char from l1
注意,对于"*l*"
的测试用例,上面的答案是正确答案,但出于错误的原因。还有其他人认为上述错误(与"*"
相关)但不在您的测试用例中。