【问题标题】:How do I manually find a substring in a string? (Java)如何手动查找字符串中的子字符串? (爪哇)
【发布时间】:2022-01-05 09:06:23
【问题描述】:
        public int lookFor(String s) {
    final int EXIST = 1;
    final int NOT_EXIST = -1; 
    int thisIndex = 0;
    int otherIndex = 0;
    char thisNext;
    char otherNext;
    

    if (s == null || s.length() == 0)
        return NOT_EXIST;
    
    for(; thisIndex < this.mainString.length() ; ) {
        
        thisNext = this.mainString.charAt(thisIndex);
        otherNext = s.charAt(otherIndex);
        
        if (thisNext == otherNext) {
            thisIndex++;
            otherIndex++;
        }
        
        else if (thisNext != otherNext)
            thisIndex++;
        
        if (otherIndex == s.length()-1)
            return EXIST;       
    }
    return NOT_EXIST;
}

这是我目前的尝试。

mainString = 我要在其中找到子字符串的主字符串。 s = 子字符串。

所以我的想法是获取两个字符串的第一个字符,看看它们是否相等。如果他们不这样做,我会得到 mainString 的第二个字符,看看它们是否相等(mainString 第二个字符到第一个字符)。如果它们不相等,我将得到 mainString 的第三个字符,依此类推。一旦它们相等,我将获取两个字符串的下一个字符并查看它们是否相等。

基本上,当 s 的索引等于 s 长度减一时,循环知道 mainString 包含 s(这意味着循环一直循环到 s 的最后一个字符 inc,因此 s 索引 == s 长度 -1)。

我尝试使用的逻辑是否不正确?或者我只是执行它不好?我很乐意得到答案!

【问题讨论】:

  • 所以您尝试使用除您自己之外的任何方法?喜欢不使用 indexOf 方法?

标签: java string loops substring


【解决方案1】:

这是我幼稚的做法:

private final int EXIST = 1;
private final int NOT_EXIST = -1;

private int lookFor(String a, String b, int index) {
     for (int i = 0; i < b.length(); i++) {
          if ((index + i) >= a.length()) return NOT_EXIST;
          if (a.charAt(index + i) != b.charAt(i)) return NOT_EXIST;
     }
     return EXIST;
}

public int lookFor(String a, String b) {
     char start = b.charAt(0);
     for (int i=0; i < a.length(); i++) {
          if (a.charAt(i) == start) {
               if (lookFor(a, b, i) == EXIST) return EXIST;
          }
     }
     return NOT_EXIST;
}

不过,我不知道你为什么会这样做:

int ret = a.contains(b) ? EXIST : NOT_EXIST

但是我想真正回答你的问题。

这是一个略微改进的版本,可满足您的“多合一方法”要求。

public static int lookFor(String a, String b) {
    // Fancy way of preventing errors when one of the strings is empty
    boolean az = a.length() == 0;
    boolean bz = b.length() == 0;
     if (az ^ bz) return NOT_EXIST;
     // Need this next line if you want to interpret two empty strings as containing eachother
     if (az && bz) return EXIST;
     char start = b.charAt(0);
     // This is known as a "label". Some say it's bad practice.
     outer:
     for (int i=0; i < a.length(); i++) {
          if (a.charAt(i) == start) {
               // Instead of using two methods, we can condense it like so
               for (int q = 0; q < b.length(); q++) {
                    if ((i + q) >= a.length()) continue outer;
                    if (a.charAt(i + q) != b.charAt(q)) continue outer;
               }
               return EXIST;
          }
     }
     return NOT_EXIST;
}

【讨论】:

  • 你能解释一下你的方法吗?而且我必须手动完成,不能使用“contains”/“indexOf”等等(这就是问题说明所说的)
  • @EladOO 当然!第一种方法将告诉我们字符串 b 是否在指定索引处的字符串 a 内,没有其他地方。我们通过从给定索引处的字符串 a 中读取字符来完成此操作,并在找到与字符串 b 中的对应字符不匹配的字符时停止。如果我们处理(字符串 b 的长度)字符而不返回,那么这意味着字符串 a 在给定索引处包含字符串 b。第二种方法获取字符串 b 中的第一个字符,并循环遍历字符串 a。如果 String a 中的当前字符匹配,则运行上述方法。
  • 谢谢!我现在明白了,这是一个非常聪明的方法。虽然我不确定是否允许我手动将外部方法添加到类中。整个事情可以用一种方法完成吗?
  • @EladOO 更新了答案。享受吧!
【解决方案2】:

要“手动”查找子字符串,您需要一个嵌套循环;即循环内的循环。

  • 外层循环尝试字符串中子字符串的所有可能起始位置。
  • 对于给定的起始位置,内部循环会根据您正在搜索的字符串测试您正在查找的字符串的所有字符。

在朴素的子字符串搜索算法中,外层循环从索引 0 开始,并将索引加 1,直到到达正在搜索的字符串的末尾。这可以在以下方面进行改进:

  • 每个非空字符串都“包含”空字符串。可能值得将其视为特殊情况。

  • 很容易看出外循环通常可以在final之前停止。如果您正在搜索长度为(例如)3 的字符串,则外部循环可以从末尾开始在 3 处停止。 (想一想……)

  • 有一些聪明的算法允许外循环跳过一些索引。如果您有兴趣,请先在 Google 上搜索“Boyer-Moore 字符串搜索”。

(注意:循环可以替换为 / 使用递归编写,但它仍然存在。)


您的代码没有嵌套循环。根据我的阅读,只有当您正在搜索的字符串位于您正在搜索的字符串的开头时,它才会找到匹配项。这是不正确的。

【讨论】:

    猜你喜欢
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 2014-02-13
    • 2017-10-27
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多