Java 以最佳方式计算草堆串中针串的出现次数?

Java 以最佳方式计算草堆串中针串的出现次数?,java,algorithm,Java,Algorithm,问题很简单,只需在“abcdsgdabcsagaabccccaabaabc”中查找“ABC”,而不使用String.split(“ABC”) 这是我提出的解决方案,我正在寻找任何可能比这个更好的解决方案 public static void main(String[] args) { String haystack = "ABCDSGDABCSAGAABCCCCAAABAABC"; String needle = "ABC"; char [] needl = needle.toCharAr

问题很简单,只需在“abcdsgdabcsagaabccccaabaabc”中查找“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);
 }
publicstaticvoidmain(字符串[]args){
字符串haystack=“abcdsgdabcsagaabccccaababc”;
线针=“ABC”;
char[]needl=needle.toCharArray();
int-needlen=针的长度();
int=0;
char hay[]=haystack.toCharArray();
int指数=0;
int chMatched=0;
对于(int i=0;i=needelen | | chMatched==0)
指数=0;
System.out.print(“\nchar-->”+hay[i]+”,带->“+needl[index]);
if(hay[i]==needl[index]){
chMatched++;
System.out.println(“,匹配”);
}否则{
chMatched=0;
指数=0;
if(hay[i]==needl[index]){
chMatched++;
System.out.print(“\nchar->”+hay[i]+”,带->“+needl[index]);
系统输出打印(“匹配”);
}否则
继续;
}
如果(chMatched==needelen){
发现++;
System.out.println(“found.Total->”+found);
}
索引++;
} 
System.out.println(“结果发现-->”+发现);
}
我花了一段时间才创建了这个。有人能提出更好的解决方案吗(如果有) 请注意,如果您觉得系统不整洁,请将其删除。

如何:

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);
}
如果你在寻找一种算法,谷歌搜索“博耶摩尔”。您可以在次线性时间内完成此操作


编辑以澄清并希望让所有纯粹主义者高兴:从形式上讲,Boyer Moore的时间限制是线性的。然而,有效的性能通常是这样的,与使用更简单的方法相比,您进行的比较要少得多,尤其是您可以跳过“haystack”字符串,而不必检查每个字符。

您说您的挑战是在字符串中查找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;
}

别人问,在什么意义上更好?基于regexp的解决方案将是最简洁和可读的(:-)。Boyer Moore(–Moore_string_search_算法)在时间(O(N))方面将是最有效的。

如果您不介意实现一个新的数据结构作为字符串的替代品,请看一看尝试:或

如果您不寻找正则表达式,而是精确匹配,则它们应该提供最快的解决方案(与搜索字符串的长度成比例)。

请查看公共类FindNeedleInHaystack{ String hayStack=“asdvkdbgkbcdgflbjadlbcnfvkvbcdxkbxcvjxbkvaldkbjaffxbcd”; 线针=“BCD”; 布尔标志=假; 公共void findNeedle(){ //下面的for循环按每个字符迭代字符串,直到达到最大长度 对于(int i=0;i
公共类针头计数
{
公共静态void main(字符串[]args)
{
字符串s=“avbvdabchjhdfabcjhkhf”,ned=“ABC”;
int nedex=-1,count=0,totalNed=0;
对于(int i=0;ined.length()-1)
nedex++;
其他的
nedex=i;
如果(s.charAt(i)=ned.charAt(nedIndex))
计数++;
其他的
{
指数=0;
计数=0;
如果(s.charAt(i)=ned.charAt(nedIndex))
计数++;
其他的
NED指数=-1;
}
if(count==ned.length())
{
NED指数=-1;
计数=0;
totalNed++;
System.out.println(totalNed+”指针位于索引=“+(i-(ned.length()-1));
}
}
系统输出打印(“总Ned=”+总Ned);
}
}

下面的代码将执行完全O(n)复杂度,因为我们正在循环n个字符的haystack。如果您想在注释代码下面捕获指针取消注释的开始和结束索引。解决方案是使用字符,而不使用Java字符串函数(模式匹配、IndexOf、substring等)使用,因为它们可能带来额外的空间/时间复杂性

        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);
char[]neederarray=needle.tocharray();
char[]hayStackArray=hayStack.toCharArray();
//java.util.LinkedList indexList=新建LinkedList();
int头;
int-tail=0;
针数=0;

虽然(最好是每行代码都缩进四个空格,这将使它更可读,并添加语法突出显示。注意:如果这是某种作业,将它添加为标记;)“更好”和“最佳”在什么方面?内存占用?速度?可维护性?性能和性能。内存不是问题。Boyer-Moore是O(N),即线性。如果你做得好,你可以跳过文本(这个问题中的“草堆”),这样你就不必看每个字符。当然,这取决于搜索字符串;如果搜索字符串只有一个字符长,那么它总是线性的。是的,从形式上来说,最坏的情况是线性的(我认为这是3n对吗?)维基百科上关于这方面的文章很好!@Pointy当然,但这并不能改变它是线性的事实。复杂性分析不关心常数,所以它是O(N)。没有普遍保证Boyer Moore会比天真的方法更快,这完全取决于搜索的字符串。@Havard复杂性分析可能不关心常量,但需要性能的人会关心。即使你没有得到保证,它也会更快,至少你有机会。应该迭代完成,每次启动t 1超出上次找到的位置(或“ABC”.length()超出索引)来计算出现的次数(这是个问题)。不,这只是说是或否。我要求计数。是的,不要使用字符串。拆分(“ABC”)好的,你的问题没有特别清楚,只是要求找到字符串“ABC”再一次,不能保证博耶·摩尔会比天真的se更高效
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);
  }
}
        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);