【问题标题】:Java: Implement String method contains() without built-in method contains()Java:在没有内置方法 contains() 的情况下实现 String 方法 contains()
【发布时间】:2013-04-13 21:37:41
【问题描述】:

我正在尝试在不使用内置 contains() 方法的情况下实现 String method contains()

这是我目前所拥有的:

public static boolean containsCS(String str, CharSequence cs) {

    char[] chs = str.toCharArray();
    int i=0,j=chs.length-1,k=0,l=cs.length();

    //String      str = "Hello Java";
    //                   0123456789
    //CharSequence cs = "llo";

    while(i<j) {
        if(str.charAt(i)!=cs.charAt(k)) {
            i++;
        }
        if(str.charAt(i)==cs.charAt(k)) {

        }
    }

    return false;
}

我只是在练习我的算法技能,结果卡住了。

有什么建议吗?

【问题讨论】:

  • 为什么不看一下String.contains()方法的源代码?
  • 值得学习一些算法。你可以从KMP algorithm开始。
  • @JBNizet 源码使用了indexOf()的方法但是我不想用。
  • 然后看indexOf()的源码。
  • 我想这是有道理的。谢谢 JB Nizet。

标签: java string contains


【解决方案1】:

仅使用 1 个循环

我对 Poran 的回答做了一些补充,效果很好:

 public static boolean contains(String main, String Substring) {
    boolean flag=false;
    if(main==null && main.trim().equals("")) {
        return flag;
    }
    if(Substring==null) {
        return flag;
    }

    char fullstring[]=main.toCharArray();
    char sub[]=Substring.toCharArray();
    int counter=0;
    if(sub.length==0) {
        flag=true;
        return flag;
    }

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

        if(fullstring[i]==sub[counter]) {
            counter++;
        } else {
            counter=0;
        }

        if(counter==sub.length) {
            flag=true;
            return flag;
        }

    }
    return flag;

}

【讨论】:

  • 这在前面重复的情况下不起作用,例如"eileen" 和 "en",为了解决这个添加 if(counter > 0){ i -= counter; } 在 for 循环的 else 部分。
  • 没有理由拥有i-= counter。您只需“重做”当前迭代,只需 if (counter &gt; 0) --i; 即可。
【解决方案2】:

这应该可以正常工作。我正在打印执行以帮助理解该过程。

public static boolean isSubstring(String original, String str){
    int counter = 0, oLength = original.length(), sLength = str.length();
    char[] orgArray = original.toCharArray(), sArray = str.toCharArray();
    for(int i = 0 ; i < oLength; i++){
        System.out.println("counter at start of loop " + counter);
        System.out.println(String.format("comparing %s with %s", orgArray[i], sArray[counter]));
        if(orgArray[i] == sArray[counter]){
            counter++;
            System.out.println("incrementing counter " + counter);
        }else{
            //Special case where the character preceding the i'th character is duplicate
            if(counter > 0){
                i -= counter;
            }
            counter = 0;
            System.out.println("resetting counter " + counter);
        }
        if(counter == sLength){
            return true;
        }
    }
    return false;
}

【讨论】:

    【解决方案3】:

    提示:

    • 使用嵌套循环。
    • 将字符提取到数组中可能是个坏主意。但如果你要这样做,你应该使用它!
    • 忽略使用快速字符串搜索算法的建议。它们仅适用于大规模搜索。 (如果您查看String.indexOf 的代码,它只是进行简单的搜索...)

    【讨论】:

      【解决方案4】:

      正如 JB Nizet 所建议的,herecontains() 的实际代码:

      2123  public boolean contains(CharSequence s) {
      2124      return indexOf(s.toString()) > -1;
      2125  }
      

      这是indexOf()的代码:

      1732     public int indexOf(String str) {
      1733         return indexOf(str, 0);
      1734     }
      

      这会导致:

       1752   public int indexOf(String str, int fromIndex) {
       1753       return indexOf(value, offset, count,
       1754                      str.value, str.offset, str.count, fromIndex);
       1755   }
      

      最终导致:

       1770   static int indexOf(char[] source, int sourceOffset, int sourceCount,
       1771                      char[] target, int targetOffset, int targetCount,
       1772                      int fromIndex) {
       1773       if (fromIndex >= sourceCount) {
       1774           return (targetCount == 0 ? sourceCount : -1);
       1775       }
       1776       if (fromIndex < 0) {
       1777           fromIndex = 0;
       1778       }
       1779       if (targetCount == 0) {
       1780           return fromIndex;
       1781       }
       1782   
       1783       char first  = target[targetOffset];
       1784       int max = sourceOffset + (sourceCount - targetCount);
       1785   
       1786       for (int i = sourceOffset + fromIndex; i <= max; i++) {
       1787           /* Look for first character. */
       1788           if (source[i] != first) {
       1789               while (++i <= max && source[i] != first);
       1790           }
       1791   
       1792           /* Found first character, now look at the rest of v2 */
       1793           if (i <= max) {
       1794               int j = i + 1;
       1795               int end = j + targetCount - 1;
       1796               for (int k = targetOffset + 1; j < end && source[j] ==
       1797                        target[k]; j++, k++);
       1798   
       1799               if (j == end) {
       1800                   /* Found whole string. */
       1801                   return i - sourceOffset;
       1802               }
       1803           }
       1804       }
       1805       return -1;
       1806   }
      

      【讨论】:

      • 谢谢,D 先生。我知道,但我只是不想使用 indexOf() 方法。因为使用indexOf() 对我没有好处。
      • 您粘贴的 indexOf() 方法不是 contains() 使用的方法。
      • @JB Nizet 被调用的只包含对这个的调用
      • 不,这不是真的。 CharSequence 包含多个字符,并且您粘贴的 indexOf() 方法仅将单个字符作为参数。
      • 嗯你是对的,更正它,我认为现在所有内容都包含在内
      【解决方案5】:

      我想出了这个:

      public static boolean isSubString(String s1, String s2) {
          if (s1.length() > s2.length())
              return false;
      
          int count = 0;
      
          //Loop until count matches needle length (indicating match) or until we exhaust haystack
          for (int j = 0; j < s2.length() && count < s1.length(); ++j) {
              if (s1.charAt(count) == s2.charAt(j)) {
                  ++count;
              }
              else {
                  //Redo iteration to handle adjacent duplicate char case
                  if (count > 0)
                      --j;
      
                  //Reset counter
                  count = 0;
              }
          }
      
          return (count == s1.length());
      }
      

      【讨论】:

        【解决方案6】:

        我最近偶然发现了这个问题,尽管我会分享一个替代解决方案。我生成具有我们要查找的字符串长度的所有子字符串,然后将它们推入哈希集中并检查其中是否包含它。

         static boolean contains(String a, String b) {
            if(a.equalsIgnoreCase(b)) {
                return true;
            }
            Set<String> allSubStrings = new HashSet<>();
            int length = b.length();
            for(int i=0; i<a.length(); ++i) {
                if(i+length <= a.length()) {
                    String sub = a.substring(i, i + length);
                    allSubStrings.add(sub);
                }
            }
            return allSubStrings.contains(b);
        }
        

        【讨论】:

          【解决方案7】:
          
              public static boolean contains(String large, String small) {
          
                  char[] largeArr = large.toCharArray();
                  char[] smallArr = small.toCharArray();
          
                  if (smallArr.length > largeArr.length)
                     return false;
          
                  for(int i = 0 ; i <= largeArr.length - smallArr.length ; i++) {
                      boolean result = true ;
                      for(int j = 0 ; j < smallArr.length ; j++) {
                           if(largeArr[i+j] != smallArr[j]) {
                               result = false;
                               break;
                           }
                           result = result && (largeArr[i+j]==smallArr[j]); 
                      }
                      if(result==true) {return true;}
                  }
          
                  return false;
              }
          
          
          

          【讨论】:

            【解决方案8】:

            由于嵌套循环,当然不是最有效的解决方案,但它似乎工作得很好。

            private static boolean contains(String s1, String s2) {
                if (s1.equals(s2)) return true;
                if (s2.length() > s1.length()) return false;
            
                boolean found = false;
                for (int i = 0; i < s1.length() - s2.length(); i++) {
                    found = true;
                    for (int k = 0; k < s2.length(); k++)
                        if (i + k < s1.length() && s1.charAt(i + k) != s2.charAt(k)) {
                            found = false;
                            break;
                        }
                    if (found) return true;
                }
                return false;
            }
            

            【讨论】:

              【解决方案9】:

              可以使用单个循环来完成。

              public boolean StringContains(String full, String part) {
                  long st = System.currentTimeMillis();
                  if(full == null || full.trim().equals("")){
                      return false;
                  }
                  if(part == null ){
                      return false;
                  }
                  char[] fullChars = full.toCharArray();
                  char[] partChars = part.toCharArray();
                  int fs = fullChars.length;
                  int ps = partChars.length;
                  int psi = 0;
                  if(ps == 0) return true;
                  for(int i=0; i< fs-1; i++){
                      if(fullChars[i] == partChars[psi]){
                          psi++; //Once you encounter the first match, start increasing the counter
                      }
                      if(psi == ps) return true;
                  }
                  long et = System.currentTimeMillis()- st;
                  System.out.println("StringContains time taken =" + et);
                  return false;
              }
              

              【讨论】:

              • 这不适用于StringContains("fofo", "foo") 这样的情况,因为当它开始迭代时,它不会在第一个字符串中的第三个字符之后自行重置。你需要的是在循环中的第一个条件之后添加 if else 像else if(psi &gt; 0) {psi = 0;} 这将重置值
              猜你喜欢
              • 2015-07-03
              • 2019-05-09
              • 2014-08-20
              • 1970-01-01
              • 2019-05-03
              • 2015-10-06
              • 1970-01-01
              • 1970-01-01
              • 2013-12-02
              相关资源
              最近更新 更多