Java 两个字符串的公共子字符串

Java 两个字符串的公共子字符串,java,algorithm,Java,Algorithm,这个特别的面试问题难住了我: 给定两个字符串S1和S2。查找最长的子字符串,其前缀为S1,后缀为S2 通过谷歌,我发现了以下解决方案,但我不太明白它在做什么 public String findLongestSubstring(String s1, String s2) { List<Integer> occurs = new ArrayList<>(); for (int i = 0; i < s1.length(); i++) {

这个特别的面试问题难住了我:

给定两个字符串S1和S2。查找最长的子字符串,其前缀为S1,后缀为S2

通过谷歌,我发现了以下解决方案,但我不太明白它在做什么

public String findLongestSubstring(String s1, String s2) {
        List<Integer> occurs = new ArrayList<>();
        for (int i = 0; i < s1.length(); i++) {
            if (s1.charAt(i) == s2.charAt(s2.length()-1)) {
                occurs.add(i);
            }
        }

        Collections.reverse(occurs);

        for(int index : occurs) {
            boolean equals = true;
            for(int i = index; i >= 0; i--) {
                if (s1.charAt(index-i) != s2.charAt(s2.length() - i - 1)) {
                    equals = false;
                    break;
                }
            }
            if(equals) {
                return s1.substring(0,index+1);
            }
        }

        return null;
    }
公共字符串findLongestSubstring(字符串s1、字符串s2){
List occurs=新建ArrayList();
对于(int i=0;i=0;i--){
如果(s1.charAt(index-i)!=s2.charAt(s2.length()-i-1)){
等于等于假;
打破
}
}
如果(等于){
返回s1.子字符串(0,索引+1);
}
}
返回null;
}
我的问题:

  • 这个解决方案是如何工作的?
    • 你是如何发现这个解决方案的
  • 是否有更直观/更简单的解决方案

  • 你从哪里找到的解决方案?它是由一个可信的、受人尊敬的程序员写的吗?如果你对此不确定,那么它可能不值得一读。人们可以编写非常复杂和低效的代码来完成非常简单的事情,而不值得理解算法

    与试图理解其他人的解决方案相比,自己想出解决方案可能更容易。我认为你通过这种方式更好地理解了这个问题,逻辑就变成了你自己的了。随着时间的推移和实践,思维过程将开始变得更加自然。熟能生巧


    无论如何,我在Python中使用了一个更简单的实现(剧透警报!)。我建议您先自己找出解决方案,然后再与我的方案进行比较。

    您从哪里找到的解决方案?它是由一个可信的、受人尊敬的程序员写的吗?如果你对此不确定,那么它可能不值得一读。人们可以编写非常复杂和低效的代码来完成非常简单的事情,而不值得理解算法

    与试图理解其他人的解决方案相比,自己想出解决方案可能更容易。我认为你通过这种方式更好地理解了这个问题,逻辑就变成了你自己的了。随着时间的推移和实践,思维过程将开始变得更加自然。熟能生巧

    无论如何,我在Python中使用了一个更简单的实现(剧透警报!)。我建议您先自己找出解决方案,然后与我的方案进行比较。

    问题的第2部分 以下是一个较短的变体:

    public String findLongestPrefixSuffix(String s1, String s2) {
    
       for( int i = Math.min(s1.length(), s2.length()); ; i--) {
          if(s2.endsWith(s1.substring(0, i))) {
             return s1.substring(0, i);
          }
       }    
    }
    
    我正在使用
    Math.min
    查找最短字符串的长度,因为我不需要也无法比较超过该长度的字符串

    someString.substring(x,y)
    返回从字符
    x
    开始并在字符
    y
    处停止读取某个字符串时得到的字符串。我从可能的最大子字符串(
    s1
    s2
    )返回到可能的最小子字符串,即空字符串。这样,当我的条件第一次为真时,它将是实现它的最大可能子字符串

    如果愿意,可以反过来,但必须引入一个变量,以节省满足条件的最长子字符串的长度:

    public static String findLongestPrefixSuffix(String s1, String s2) {
    
       if (s1.equals(s2)) { // this part is optional and will 
          return s1;        // speed things up if s1 is equal to s2
       }                    //
    
       int max = 0;
       for (int i = 0; i < Math.min(s1.length(), s2.length()); i++) {
          if (s2.endsWith(s1.substring(0, i))) {
             max = i;
          }
       }
       return s1.substring(0, max);
    }
    
    公共静态字符串findLongestPrefixSuffix(字符串s1、字符串s2){
    如果(s1.equals(s2)){//这部分是可选的,将
    返回s1;//如果s1等于s2,则加快速度
    }                    //
    int max=0;
    对于(int i=0;i
    作为记录:在后一个示例中,您可以从
    i=1
    开始,以获得一点点额外的性能。除此之外,您还可以使用
    i
    指定后缀的长度(至少为您想要的长度)如果写入
    Math.min(s1.length(),s2.length())-x
    ,则可以使用
    x
    指定找到的子字符串的最长长度。对于第一种解决方案,这两种情况都是可能的,但最小长度更复杂一些


    你问题的第一部分 在
    Collections.reverse上面的部分中,代码作者在
    s1
    中搜索
    s2
    最后一个字母所在的所有位置,并保存该位置

    下面的内容本质上就是我的算法所做的,不同的是,他不检查每个子字符串,只检查那些以
    s2
    的最后一个字母结尾的子字符串

    这是一种加快速度的优化。如果速度不是那么重要,我天真的实现就足够了

    你问题的第二部分 以下是一个较短的变体:

    public String findLongestPrefixSuffix(String s1, String s2) {
    
       for( int i = Math.min(s1.length(), s2.length()); ; i--) {
          if(s2.endsWith(s1.substring(0, i))) {
             return s1.substring(0, i);
          }
       }    
    }
    
    我正在使用
    Math.min
    查找最短字符串的长度,因为我不需要也无法比较超过该长度的字符串

    someString.substring(x,y)
    返回从字符
    x
    开始并在字符
    y
    处停止读取某个字符串时得到的字符串。我从可能的最大子字符串(
    s1
    s2
    )返回到可能的最小子字符串,即空字符串。这样,当我的条件第一次为真时,它将是实现它的最大可能子字符串

    如果愿意,可以反过来,但必须引入一个变量,以节省满足条件的最长子字符串的长度:

    public static String findLongestPrefixSuffix(String s1, String s2) {
    
       if (s1.equals(s2)) { // this part is optional and will 
          return s1;        // speed things up if s1 is equal to s2
       }                    //
    
       int max = 0;
       for (int i = 0; i < Math.min(s1.length(), s2.length()); i++) {
          if (s2.endsWith(s1.substring(0, i))) {
             max = i;
          }
       }
       return s1.substring(0, max);
    }
    
    公共静态字符串findLongestPrefixSuffix(字符串s1、字符串s2){
    如果(s1.equals(s2)){//这部分是可选的,将
    返回s1;