📜  最长重复和非重叠子串

📅  最后修改于: 2021-09-17 16:04:52             🧑  作者: Mango

给定一个字符串str ,找到其中最长的重复非重叠子字符串。换句话说,找到 2 个不重叠的最大长度的相同子串。如果存在多个这样的子字符串,则返回其中任何一个。
例子:

Input : str = "geeksforgeeks"
Output : geeks

Input : str = "aab"
Output : a

Input : str = "aabaabaaba"
Output : aaba

Input : str = "aaaaaaaaaaa"
Output : aaaaa

Input : str = "banana"
Output : an 
         or na

天真的解决方案:通过获取所有可能的子字符串并为所有子字符串检查剩余的(非重叠)字符串,如果存在相同的子字符串,可以轻松解决该问题。总共有 O(n 2 ) 个子串,并且根据剩余的字符串检查它们将花费 O(n) 时间。所以上述解决方案的总时间复杂度是 O(n 3 )。
动态规划:这个问题可以使用动态规划在 O(n 2 ) 时间内解决。基本思想是为字符串str 中的所有前缀找到最长的重复后缀。

Length of longest non-repeating substring can be recursively
defined as below.

LCSRe(i, j) stores length of the matching and
            non-overlapping substrings ending 
            with i'th and j'th characters.

If str[i-1] == str[j-1] && (j-i) > LCSRe(i-1, j-1)
     LCSRe(i, j) = LCSRe(i-1, j-1) + 1, 
Else
     LCSRe(i, j) = 0

Where i varies from 1 to n and 
      j varies from i+1 to n

为了避免重叠,我们必须确保后缀的长度在任何时候都小于 (ji)。
LCSRe(i, j) 的最大值提供了最长重复子串的长度,并且可以使用公共后缀的长度和结束索引找到子串本身。
下面是递归的实现。

C++
// C++ program to find the longest repeated
// non-overlapping substring
#include
using namespace std;
 
// Returns the longest repeating non-overlapping
// substring in str
string longestRepeatedSubstring(string str)
{
    int n = str.length();
    int LCSRe[n+1][n+1];
 
    // Setting all to 0
    memset(LCSRe, 0, sizeof(LCSRe));
 
    string res; // To store result
    int res_length  = 0; // To store length of result
 
    // building table in bottom-up manner
    int i, index = 0;
    for (i=1; i<=n; i++)
    {
        for (int j=i+1; j<=n; j++)
        {
            // (j-i) > LCSRe[i-1][j-1] to remove
            // overlapping
            if (str[i-1] == str[j-1] &&
                LCSRe[i-1][j-1] < (j - i))
            {
                LCSRe[i][j] = LCSRe[i-1][j-1] + 1;
 
                // updating maximum length of the
                // substring and updating the finishing
                // index of the suffix
                if (LCSRe[i][j] > res_length)
                {
                    res_length = LCSRe[i][j];
                    index = max(i, index);
                }
            }
            else
                LCSRe[i][j] = 0;
        }
    }
 
    // If we have non-empty result, then insert all
    // characters from first character to last
    // character of string
    if (res_length > 0)
        for (i = index - res_length + 1; i <= index; i++)
            res.push_back(str[i-1]);
 
    return res;
}
 
// Driver program to test the above function
int main()
{
    string str = "geeksforgeeks";
    cout << longestRepeatedSubstring(str);
    return 0;
}


Java
// Java program to find the longest repeated
// non-overlapping substring
 
class GFG {
 
// Returns the longest repeating non-overlapping
// substring in str
    static String longestRepeatedSubstring(String str) {
        int n = str.length();
        int LCSRe[][] = new int[n + 1][n + 1];
 
        String res = ""; // To store result
        int res_length = 0; // To store length of result
 
        // building table in bottom-up manner
        int i, index = 0;
        for (i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                // (j-i) > LCSRe[i-1][j-1] to remove
                // overlapping
                if (str.charAt(i - 1) == str.charAt(j - 1)
                        && LCSRe[i - 1][j - 1] < (j - i)) {
                    LCSRe[i][j] = LCSRe[i - 1][j - 1] + 1;
 
                    // updating maximum length of the
                    // substring and updating the finishing
                    // index of the suffix
                    if (LCSRe[i][j] > res_length) {
                        res_length = LCSRe[i][j];
                        index = Math.max(i, index);
                    }
                } else {
                    LCSRe[i][j] = 0;
                }
            }
        }
 
        // If we have non-empty result, then insert all
        // characters from first character to last
        // character of String
        if (res_length > 0) {
            for (i = index - res_length + 1; i <= index; i++) {
                res += str.charAt(i - 1);
            }
        }
 
        return res;
    }
 
// Driver program to test the above function
    public static void main(String[] args) {
        String str = "geeksforgeeks";
        System.out.println(longestRepeatedSubstring(str));
    }
}
// This code is contributed by Rajput-JI


Python 3
# Python 3 program to find the longest repeated
# non-overlapping substring
 
# Returns the longest repeating non-overlapping
# substring in str
def longestRepeatedSubstring(str):
 
    n = len(str)
    LCSRe = [[0 for x in range(n + 1)]
                for y in range(n + 1)]
 
    res = "" # To store result
    res_length = 0 # To store length of result
 
    # building table in bottom-up manner
    index = 0
    for i in range(1, n + 1):
        for j in range(i + 1, n + 1):
             
            # (j-i) > LCSRe[i-1][j-1] to remove
            # overlapping
            if (str[i - 1] == str[j - 1] and
                LCSRe[i - 1][j - 1] < (j - i)):
                LCSRe[i][j] = LCSRe[i - 1][j - 1] + 1
 
                # updating maximum length of the
                # substring and updating the finishing
                # index of the suffix
                if (LCSRe[i][j] > res_length):
                    res_length = LCSRe[i][j]
                    index = max(i, index)
                 
            else:
                LCSRe[i][j] = 0
 
    # If we have non-empty result, then insert
    # all characters from first character to
    # last character of string
    if (res_length > 0):
        for i in range(index - res_length + 1,
                                    index + 1):
            res = res + str[i - 1]
 
    return res
 
# Driver Code
if __name__ == "__main__":
     
    str = "geeksforgeeks"
    print(longestRepeatedSubstring(str))
 
# This code is contributed by ita_c


C#
// C# program to find the longest repeated
// non-overlapping substring
using System;
  
public class GFG {
  
// Returns the longest repeating non-overlapping
// substring in str
    static String longestRepeatedSubstring(String str) {
        int n = str.Length;
        int [,]LCSRe = new int[n + 1,n + 1];
  
        String res = ""; // To store result
        int res_length = 0; // To store length of result
  
        // building table in bottom-up manner
        int i, index = 0;
        for (i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                // (j-i) > LCSRe[i-1][j-1] to remove
                // overlapping
                if (str[i - 1] == str[j - 1]
                        && LCSRe[i - 1,j - 1] < (j - i)) {
                    LCSRe[i,j] = LCSRe[i - 1,j - 1] + 1;
  
                    // updating maximum length of the
                    // substring and updating the finishing
                    // index of the suffix
                    if (LCSRe[i,j] > res_length) {
                        res_length = LCSRe[i,j];
                        index = Math.Max(i, index);
                    }
                } else {
                    LCSRe[i,j] = 0;
                }
            }
        }
  
        // If we have non-empty result, then insert all
        // characters from first character to last
        // character of String
        if (res_length > 0) {
            for (i = index - res_length + 1; i <= index; i++) {
                res += str[i - 1];
            }
        }
  
        return res;
    }
  
// Driver program to test the above function
    public static void Main() {
        String str = "geeksforgeeks";
        Console.WriteLine(longestRepeatedSubstring(str));
    }
}
// This code is contributed by Rajput-JI


Javascript


输出:

geeks

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程