给定字符串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