簡體   English   中英

兩個字符串的共同子字符串

[英]Common Substring of two strings

這個特殊的面試問題讓我難過:

Given two Strings S1 and S2. Find the longest Substring which is a Prefix of S1 and suffix of S2 Given two Strings S1 and S2. Find the longest Substring which is a Prefix of S1 and suffix of S2

通過Google,我遇到了以下解決方案,但並不太了解它在做什么。

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;
    }

我的問題:

  1. 該解決方案如何運作?
    • 以及如何找到這個解決方案?
  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來查找最短String的長度,因為我不需要而且不能進行更多比較。

someString.substring(x,y)返回您從字符x開始到字符y讀取someString時獲得的字符串。 我從可能的最大子字符串( s1s2 )倒退到最小的子字符串(空字符串)。 這樣,我的條件第一次為真時,將最大可能滿足該條件的子串。

如果您願意,可以采用相反的方法,但是您必須引入一個變量,該變量保存到目前為止滿足條件的最長找到子字符串的長度:

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);
}

作為記錄:在后面的示例中,您可以從i = 1開始,以獲得一點點額外的性能。 最重要的是,您可以使用i來指定后綴至少要保留多長時間。 ;)如果Math.min(s1.length(), s2.length()) - x ,則可以使用x來指定找到的子字符串最多可以有多長時間。 這兩種情況在第一種解決方案中都是可行的,但是最小長度會涉及更多的問題。 ;)


問題的第1部分

Collections.reverse上方的部分中,代碼的作者在s1中搜索s2的最后一個字母所在的所有位置,然后保存該位置。

接下來的內容本質上是我的算法所做的事情,不同之處在於,他不檢查每個子字符串,而是僅檢查那些以s2的最后一個字母結尾的子字符串。

這是某種加快速度的優化。 如果速度不是那么重要,那么我幼稚的實現就足夠了。 ;)

您在哪里找到該解決方案? 它是由可信的,受人尊敬的編碼器編寫的嗎? 如果您不確定,則可能不值得閱讀。 一個人可能會寫出非常復雜而效率低下的代碼來完成一件非常簡單的事情,這不值得理解該算法。

與其嘗試了解別人的解決方案,不如自己想出辦法。 我認為您以這種方式更好地理解了問題,並且邏輯變成了自己的邏輯。 隨着時間的流逝和實踐,思維過程將開始變得更加自然。 實踐使完美。

無論如何,我在這里放置了一個更簡單的Python實現(劇透警報!)。 我建議您先自己找出解決方案,然后再與我比較。

Apache公共語言lang3, StringUtils.getCommonPrefix()

Java很難通過stdlib提供有用的東西。 從好的方面來說,幾乎總是有來自Apache的一些合理工具。

我將@TheMorph的答案轉換為javascript。 希望這對js開發人員有所幫助

if (typeof String.prototype.endsWith !== 'function') {
    String.prototype.endsWith = function(suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}

function findLongestPrefixSuffix(s2, s1) {

   for( var i = Math.min(s1.length, s2.length); ; i--) {
      if(s2.endsWith(s1.substring(0, i))) {
         return s1.substring(0, i);
      }
   }    
}

console.log(findLongestPrefixSuffix('abc', 'bcd')); // result: 'bc'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM