计算以相同子字符串开头和结尾的最大子字符串的长度

时间:2010-12-26 09:44:01

标签: java algorithm string recursion

以下是问题陈述:

PS:给定一个字符串和一个非空的子字符串sub,递归计算以sub开头和结尾的最大子字符串并返回其长度。

Examples:
strDist("catcowcat", "cat") → 9
strDist("catcowcat", "cow") → 3
strDist("cccatcowcatxx", "cat") → 9

以下是我的代码:        (没有递归)//因为我发现很难用递归实现。

    public int strDist(String str, String sub){    
        int idx = 0;     
        int max;    
        if (str.isEmpty()) max = 0;    
        else max=1;                        
        while ((idx = str.indexOf(sub, idx)) != -1){     
            int previous=str.indexOf(sub, idx);     
            max = Math.max(max,previous);     
            idx++;                           
        }     
     return max;    
   }

如下图所示,它为少数人工作,但其他人则返回FAIL。

Expected This Run
strDist("catcowcat", "cat") → 9 6 FAIL
strDist("catcowcat", "cow") → 3 3 OK
strDist("cccatcowcatxx", "cat") → 9 8 FAIL
strDist("abccatcowcatcatxyz", "cat") → 12 12 OK
strDist("xyx", "x") → 3 2 FAIL
strDist("xyx", "y") → 1 1 OK
strDist("xyx", "z") → 0 1 FAIL
strDist("z", "z") → 1 1 OK
strDist("x", "z") → 0 1 FAIL
strDist("", "z") → 0 0 OK
strDist("hiHellohihihi", "hi") → 13 11 FAIL
strDist("hiHellohihihi", "hih") → 5 9 FAIL
strDist("hiHellohihihi", "o") → 1 6 FAIL
strDist("hiHellohihihi", "ll") → 2 4 FAIL

你能告诉我代码有什么问题,以及如何以sub的长度返回以sub开头和结尾的最大子字符串。

6 个答案:

答案 0 :(得分:8)

有一个简单的解决方案,效率更高。找到子字符串的第一个和最后一个出现,你就得到了答案。无需搜索所有事件。

public int strDist(String str, String sub) {
  int first = str.indexOf(sub);
  if (first == -1)
    return 0;
  int last = str.lastIndexOf(sub);
  return last - first + sub.length();
}

http://ideone.com/3mgbK

您的代码的问题是您要返回最后一次出现的子字符串的索引。您似乎也试图找到最后一次出现,最后一行至少应为max - previous,但是您还需要添加子串的长度max - previous + sub.length() 。您还需要在while循环之外移动previous的声明。但是你找到了第二次最后一次和最后一次出现之间的距离,如果没有恰好两次出现(例如"foocatbar""catfoocatbarcat"),它将会失败。

递归地解决这个问题有点过分,首先是因为你不能使用内置的String.indexOf()函数。但由于这是家庭作业,这是一个快速的尝试:

public static int indexOf(String str, String sub, int start, int direction) {
  if (start < 0 || start > str.length() - sub.length())
    return -1;
  if (str.substring(start, start + sub.length()).equals(sub))
    return start;
  return indexOf(str, sub, start+direction, direction);
}

public static int strDistRecursive(String str, String sub) {
  int first = indexOf(str, sub, 0, 1);
  if (first == -1)
    return 0;
  int last = indexOf(str, sub, str.length() - sub.length(), -1);
  return last - first + sub.length();
}

http://ideone.com/f6bok

答案 1 :(得分:2)

我在这里发布我的递归解决方案。它背后的逻辑是从左侧切断,直到在开始时找到sub,并从右切断,直到最后找到sub。

public int strDist(String str, String sub) 
{
    if (0 == str.length())
    {
        return 0;
    }
    else if (!str.startsWith(sub))
    {
        //chop from left
        return strDist(str.substring(1), sub);    
    }
    else if (!str.endsWith(sub))
    {
        //chop from right
        return strDist(str.substring(0, str.length() - 1), sub);
    }
    else if (str.startsWith(sub) && str.endsWith(sub))
    {
        //got a substring subXXXsub
        return str.length();
    }
    return 0;
}

答案 2 :(得分:1)

这个问题的简单解决方案是计算主字符串中子字符串的第一个索引和lastindex。但是如果你真的需要用递归来做,那么这就是代码。

public int strDist(String str, String sub) {
   int n = str.length();
   if(n==0) return 0; 
   if (str.startsWith(sub)) return strBack(str,sub);
   return strDist(str.substring(1) , sub);
 }

public int strBack(String str, String sub) { 
int n = str.length();
if (n ==0) return 0;
if(str.endsWith(sub)) return n ;
 return strBack(str.substring(0,n-1),sub);
  }

整个方法是strDist函数从头开始查找子字符串,strBack从头开始查找sub,如果没有找到str,则由一个char剥离。因此,一旦在strDist的start处找到sub,则调用strBack并从末尾查看sub,如果找到,则剥离的str是我们需要的最长字符串。它的长度返回。

答案 3 :(得分:0)

hi I implemented the same problem with some other manner .. 

{{{

   public int strDist(String str, String sub) {
   int i = str.indexOf(sub);
   if(i==-1)  return 0;

   if(str.endsWith(sub))
      return str.length(); 

   return strDist(str.substring(i,str.length()-1),sub);
   }

}}}

this gives all correct but was wrong for other testes... Dont know y..

答案 4 :(得分:0)

有一个很好的简短递归解决方案。 对于其他一些呈现的解决方案而言,这不是一种创新,但它更短,更清晰,更容易理解:

public int strDist(String str, String sub) {
  if (str.length()==0) return 0;
  if (!str.startsWith(sub))
      return strDist(str.substring(1),sub);
  if (!str.endsWith(sub))
    return strDist(str.substring(0,str.length()-1),sub);
  return str.length();
}

答案 5 :(得分:0)

这是我的解决方案版本。它应该正常工作 - 但是,在网站(CODINGBAT)我无法通过检查。

<code>
public int strDist(String str, String sub)
{

if(str.length()<1||!str.contains(sub))return 0; 
		if(str.substring(0,sub.length()).equals(sub))
		{
			String s=str.substring(1);
			if(!s.contains(sub))
			return sub.length();
			else
			{	
				
				int t=s.indexOf(sub)+sub.length()+1;
				return t+strDist(s.substring(s.indexOf(sub)+sub.length()),sub);
			}		
		}	
		return strDist(str.substring(1),sub);	

	
}</code>