计算Haystack字符串中针头串的出现,最佳?

时间:2010-03-25 13:26:11

标签: java algorithm

问题很简单在“ABCDSGDABCSAGAABCCCCAAABAABC”中查找“ABC”而不使用String.split(“ABC”)

这是我提出的解决方案,我正在寻找可能比这个更好的解决方案。

public static void main(String[] args) {
 String haystack = "ABCDSGDABCSAGAABCCCCAAABAABC";
 String needle = "ABC";
 char [] needl = needle.toCharArray();
 int needleLen = needle.length();
 int found=0;
 char hay[] = haystack.toCharArray();
 int index =0;
 int chMatched =0;

 for (int i=0; i<hay.length; i++){

  if (index >= needleLen || chMatched==0)
   index=0;
  System.out.print("\nchar-->"+hay[i] + ", with->"+needl[index]);

  if(hay[i] == needl[index]){
   chMatched++;
   System.out.println(", matched");
  }else {
   chMatched=0;
   index=0;
   if(hay[i] == needl[index]){
    chMatched++;
    System.out.print("\nchar->"+hay[i] + ", with->"+needl[index]);
    System.out.print(", matched");
   }else
   continue;
  }

  if(chMatched == needleLen){
   found++;
   System.out.println("found. Total ->"+found);
  }
  index++;
 } 
 System.out.println("Result Found-->"+found);
 }

我花了一段时间创造了这个。有人可以提出更好的解决方案(如果有的话) 附:如果sysouts看起来很麻烦,请删除它们。

10 个答案:

答案 0 :(得分:5)

怎么样:

boolean found = haystack.indexOf("ABC") >= 0;

**编辑 - 问题询问出现次数,所以这里是以上的修改版本:

public static void main(String[] args)
{
    String needle = "ABC";
    String haystack = "ABCDSGDABCSAGAABCCCCAAABAABC";

    int numberOfOccurences = 0;
    int index = haystack.indexOf(needle);
    while (index != -1)
    {
        numberOfOccurences++;
        haystack = haystack.substring(index+needle.length());
        index = haystack.indexOf(needle);
    }

    System.out.println("" + numberOfOccurences);
}

答案 1 :(得分:3)

如果您正在寻找算法,请谷歌搜索“Boyer-Moore”。您可以在亚线性时间内完成此操作。

编辑澄清并希望让所有纯粹主义者感到高兴:从正式来讲,Boyer-Moore的时间是线性的。但是,有效的性能通常会比使用更简单的方法进行更少的比较,特别是您可以经常跳过“haystack”字符串,而无需检查每个字符。

答案 2 :(得分:1)

你说你的挑战是在字符串中找到ABC。如果您只需要知道字符串中是否存在ABC,那么简单的indexOf()测试就足够了。

如果你需要知道发生的次数,就像你发布的代码试图找到的那样,一个简单的方法就是使用正则表达式:

public static int countOccurrences(string haystack, string regexToFind) {
   Pattern p = Pattern.compile(regexToFind);
   Matcher m = p.matcher(haystack); // get a matcher object
   int count = 0;
   while(m.find()) {
       count++;
   }
   return count;
}

答案 3 :(得分:1)

答案 4 :(得分:1)

public class NeedleCount
{
  public static void main(String[] args)
  {
    String s="AVBVDABCHJHDFABCJKHKHF",ned="ABC";
    int nedIndex=-1,count=0,totalNed=0;
    for(int i=0;i<s.length();i++)
    {
      if(i>ned.length()-1)
        nedIndex++;
      else
        nedIndex=i;
      if(s.charAt(i)==ned.charAt(nedIndex))
        count++;
      else
      {
        nedIndex=0;
        count=0;
         if(s.charAt(i)==ned.charAt(nedIndex))
          count++;
        else
          nedIndex=-1;
      }
      if(count==ned.length())
      {
        nedIndex=-1;
        count=0;
        totalNed++;
        System.out.println(totalNed+" needle found at index="+(i-(ned.length()-1)));
      }
    }
    System.out.print("Total Ned="+totalNed);
  }
}

答案 5 :(得分:0)

考虑正则表达式,模式和匹配器类怎么样?查看this教程

答案 6 :(得分:0)

其他人问,在什么意义上更好?基于正则表达式的解决方案将是最简洁和可读的(:-))。 Boyer-Moore(http://en.wikipedia.org/wiki/Boyer - Moore_string_search_algorithm)在时间(O(N))方面效率最高。

答案 7 :(得分:0)

如果您不介意将新数据结构作为字符串的替代品,请查看试用:http://c2.com/cgi/wiki?StringTriehttp://en.wikipedia.org/wiki/Trie

如果你没有寻找正则表达式而是完全匹配,他们应该提供最快的解决方案(与搜索字符串的长度成比例)。

答案 8 :(得分:0)

    public class FindNeedleInHaystack {

        String hayStack="ASDVKDBGKBCDGFLBJADLBCNFVKVBCDXKBXCVJXBCVKFALDKBJAFFXBCD";
        String needle="BCD";
        boolean flag=false;

        public void findNeedle() {
//Below for loop iterates the string by each character till reaches max length
            for(int i=0;i<hayStack.length();i++) {  
//When i=n (0,1,2... ) then we are at nth character of hayStack. Let's start comparing nth char of hayStach with first char of needle
                if(hayStack.charAt(i)==needle.charAt(0)) {
//if condition return true, we reach forloop which iterates needle by lenghth.
//Now needle(BCD) first char is 'B' and nth char of hayStack is 'B'. Then let's compare remaining characters of needle with haystack using below loop. 
                    for(int j=0;j<needle.length();j++) {
//for example at i=9 is 'B', i+j is i+0,i+1,i+2...
//if condition return true, loop continues or else it will break and goes to i+1
                        if(hayStack.charAt(i+j)==needle.charAt(j)) {
                            flag=true;
                        } else {
                            flag=false;
                            break;
                        }
                    }
                    if(flag) {
                        System.out.print(i+" ");
                    }
                }                               
            }
        }
    }

答案 9 :(得分:0)

下面的代码将完全执行O(n)复杂度,因为我们循环了haystack的n个字符。如果要捕获注释代码下方的针的开始和结束索引。解决方案是围绕使用字符进行游戏,并且不使用Java String函数(模式匹配,IndexOf,子字符串等),因为它们可能带来额外的空间/时间复杂性

        char[] needleArray = needle.toCharArray();
        char[] hayStackArray = hayStack.toCharArray();
        //java.util.LinkedList<Pair<Integer,Integer>> indexList = new LinkedList<>();

        int head;
        int tail = 0;
        int needleCount = 0;

        while(tail<hayStackArray.length){

            head = tail;
            boolean proceed = false;
            for(int j=0;j<needleArray.length;j++){
                if(head+j<hayStackArray.length && hayStackArray[head+j]==needleArray[j]){
                    tail = head+j;
                    proceed = true;
                }else{
                    proceed = false;
                    break;
                }
            }

            if(proceed){
               // indexList.add(new Pair<>(head,tail));
                needleCount++;
            }
            ++tail;
        }

        System.out.println(needleCount);
        //System.out.println(indexList);