【问题标题】:Find if string contains the substring without Java.substring查找字符串是否包含没有 Java.substring 的子字符串
【发布时间】:2017-04-27 07:50:52
【问题描述】:

设计一个函数 hasCheated(String s1, String s2, int N) 如果两个字符串 s1, s2 有一个至少长度为 N 的公共子字符串,则返回 true。不使用 .contains,.substring强>

是否需要转换为 char 数组或类似的方法?

我正在考虑找到最长的公共子字符串,然后再次查看它N。有哪些方法可以解决这个问题?

【问题讨论】:

标签: java string algorithm


【解决方案1】:

首先查找最长的公共子字符串将比仅检查是否存在至少给定大小的匹配项要慢。您可以在找到匹配项后立即停止,即使可能有更长的匹配项。

我将构建一个哈希集(如果要求更复杂,则为哈希映射),它代表所有长度为 N 的子字符串(不实际创建这些子字符串),并使用它来扫描长度为 N 的字符串以查找可能匹配。

您可以在 O(M) 时间内完成此操作,其中 M 是最长字符串的长度。

你可以像这样创建一个子字符串类。

class Substring {
    final String s;
    final int offset, length, hashCode;

    Substring(String s, int offset, int length) {
        this.s = s;
        this.offset = offset;
        this.length = length;
        this.hashCode = hashCode(s, offset, length); // define to taste
    }

    public int hashCode() { return hashCode; }

    public boolean equals(Object o) {
       if (!(o instanceof Substring)) return false;
       Substring ss = (Substring) s;
       if (hashCode != ss.hashCode || length != ss.length) return false;
       for (int i = 0; i < length; i++) 
           if (s.charAt(i) != ss.s.charAt(i))
               return false;
       return true;
    }
}

要构建 HashSet,您可以在 O(n) 中执行以下操作,其中 n 是 s1.length()

Set<Substring> substrings = new HashSet<>();
for (int i = 0; i < s1.length() - n; i++) {
    Substring ss = new Substring(s1, i, n);
    substrings.add(ss);
}

要搜索匹配项,您可以在O(n) 中执行以下操作,其中 n 是 s2.length()

for (int i = 0; i < s2.length() - n; i++) {
    Substring ss = new Substring(s2, i, n);
    if (substrings.contains(ss))
         return true; // found a match.
}

【讨论】:

  • 也许,作为一个有用的答案,您应该进一步解释如何在不创建子字符串的情况下构建子字符串的哈希图。
  • @Andreas 添加了一个简单的例子。
【解决方案2】:

所以,如果没有containssubstring,我假设您的意思是不使用任何 Java API。这是一个使用动态规划的实现:

public static boolean hashCheated(String a, String b, int N) {
    int m = a.length();
    int n = b.length();

    int max = 0;

    int[][] dp = new int[m][n];

    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            if(a.charAt(i) == b.charAt(j)){
                if(i==0 || j==0){
                    dp[i][j]=1;
                }else{
                    dp[i][j] = dp[i-1][j-1]+1;
                }

                if(max < dp[i][j])
                    max = dp[i][j];
            }

        }
    }

    return (max >= N);
}

【讨论】:

  • 时间和内存使用量为 O(m*n)。
  • 是的,这是在不使用 Java API 的情况下可能实现的众多方法之一,并且每种方法都有时空权衡。可能不是最好的方法。
  • 如果您考虑获得有效解决方案的时间(即开发人员的时间),那非常好。 :)
  • “不使用任何 Java API”是什么意思?您的代码同时使用了length()charAt(),它们都是Java API 方法。它们不亚于contains()substring() 的“Java API”。
猜你喜欢
  • 2011-11-09
  • 2013-05-18
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2021-12-05
  • 2014-11-22
  • 2013-02-05
  • 1970-01-01
相关资源
最近更新 更多