Vzhledem k a řetězec s úkolem je najít nejdelší opakující se nepřekrývající se podřetězec v něm. Jinými slovy najít 2 stejné podřetězce z maximální délka které se nepřekrývají. Pokud takový řetězec neexistuje, vraťte -1.
Poznámka: Více odpovědí je možné, ale musíme je vrátit podřetězec jehož první výskyt je dříve.
Příklady:
Vstup: s = 'acdcdcdc'
výstup: 'AC/DC'
Vysvětlení: Řetězec 'acdc' je nejdelší podřetězec s, který se opakuje, ale nepřekrývá.Vstup: s = 'geeksforgeeks'
výstup: 'geekové'
Vysvětlení: Řetězec 'geeks' je nejdelší podřetězec s, který se opakuje, ale nepřekrývá.
Obsah
- Použití metody hrubé síly - O(n^3) času a O(n) prostoru
- Použití DP shora dolů (memoizace) – O(n^2) čas a O(n^2) prostor
- Použití DP zdola nahoru (tabulka) – O(n^2) čas a O(n^2) prostor
- Použití Space Optimized DP – O(n^2) Time a O(n) Space
Použití metody hrubé síly - O(n^3) času a O(n) prostoru
C++Smyslem je generovat všechny možné podřetězce a zkontrolujte, zda podřetězec existuje v zbývající řetězec. Pokud existuje podřetězec a jeho délka je větší než podřetězec odpovědi a poté nastavte odpověď na aktuální podřetězec.
// C++ program to find longest repeating // and non-overlapping substring // using recursion #include using namespace std; string longestSubstring(string& s) { int n = s.length(); string ans = ''; int len = 0; int i = 0 j = 0; while (i < n && j < n) { string curr = s.substr(i j - i + 1); // If substring exists compare its length // with ans if (s.find(curr j + 1) != string::npos && j - i + 1 > len) { len = j - i + 1; ans = curr; } // Otherwise increment i else i++; j++; } return len > 0 ? ans : '-1'; } int main() { string s = 'geeksforgeeks'; cout << longestSubstring(s) << endl; return 0; }
Java // Java program to find longest repeating // and non-overlapping substring // using recursion class GfG { static String longestSubstring(String s) { int n = s.length(); String ans = ''; int len = 0; int i = 0 j = 0; while (i < n && j < n) { String curr = s.substring(i j + 1); // If substring exists compare its length // with ans if (s.indexOf(curr j + 1) != -1 && j - i + 1 > len) { len = j - i + 1; ans = curr; } // Otherwise increment i else i++; j++; } return len > 0 ? ans : '-1'; } public static void main(String[] args) { String s = 'geeksforgeeks'; System.out.println(longestSubstring(s)); } }
Python # Python program to find longest repeating # and non-overlapping substring # using recursion def longestSubstring(s): n = len(s) ans = '' lenAns = 0 i j = 0 0 while i < n and j < n: curr = s[i:j + 1] # If substring exists compare its length # with ans if s.find(curr j + 1) != -1 and j - i + 1 > lenAns: lenAns = j - i + 1 ans = curr # Otherwise increment i else: i += 1 j += 1 if lenAns > 0: return ans return '-1' if __name__ == '__main__': s = 'geeksforgeeks' print(longestSubstring(s))
C# // C# program to find longest repeating // and non-overlapping substring // using recursion using System; class GfG { static string longestSubstring(string s) { int n = s.Length; string ans = ''; int len = 0; int i = 0 j = 0; while (i < n && j < n) { string curr = s.Substring(i j - i + 1); // If substring exists compare its length // with ans if (s.IndexOf(curr j + 1) != -1 && j - i + 1 > len) { len = j - i + 1; ans = curr; } // Otherwise increment i else i++; j++; } return len > 0 ? ans : '-1'; } static void Main(string[] args) { string s = 'geeksforgeeks'; Console.WriteLine(longestSubstring(s)); } }
JavaScript // JavaScript program to find longest repeating // and non-overlapping substring // using recursion function longestSubstring(s) { const n = s.length; let ans = ''; let len = 0; let i = 0 j = 0; while (i < n && j < n) { const curr = s.substring(i j + 1); // If substring exists compare its length // with ans if (s.indexOf(curr j + 1) !== -1 && j - i + 1 > len) { len = j - i + 1; ans = curr; } // Otherwise increment i else i++; j++; } return len > 0 ? ans : '-1'; } const s = 'geeksforgeeks'; console.log(longestSubstring(s));
Výstup
geeks
Použití DP shora dolů (memoizace) – O(n^2) čas a O(n^2) prostor
Přístup je spočítat nejdelší opakující se přípona pro všechny předpony páry v řetězec s . Pro indexy i a j -li s[i] == s[j] pak rekurzivně vypočítat přípona (i+1 j+1) a nastavit přípona (i j) jako min(přípona(i+1 j+1) + 1 j - i - 1) na zabránit překrývání . Pokud se znaky neshodují nastavit příponu (i j) = 0.
Poznámka:
- Aby se zabránilo překrývání, musíme zajistit, aby délka přípona je menší než (j-i) v každém okamžiku.
- Maximální hodnota přípona (i j) poskytuje délku nejdelšího opakujícího se podřetězce a samotný podřetězec lze najít pomocí délky a počátečního indexu společné přípony.
- přípona (i j) ukládá délku nejdelší společné přípony mezi indexy já a j zajistit to nepřesahuje j - i - 1 aby nedošlo k překrytí.
// C++ program to find longest repeating // and non-overlapping substring // using memoization #include using namespace std; int findSuffix(int i int j string &s vector<vector<int>> &memo) { // base case if (j == s.length()) return 0; // return memoized value if (memo[i][j] != -1) return memo[i][j]; // if characters match if (s[i] == s[j]) { memo[i][j] = 1 + min(findSuffix(i + 1 j + 1 s memo) j - i - 1); } else { memo[i][j] = 0; } return memo[i][j]; } string longestSubstring(string s) { int n = s.length(); vector<vector<int>> memo(n vector<int>(n -1)); // find length of non-overlapping // substrings for all pairs (ij) for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { findSuffix(i j s memo); } } string ans = ''; int ansLen = 0; // If length of suffix is greater // than ansLen update ans and ansLen for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (memo[i][j] > ansLen) { ansLen = memo[i][j]; ans = s.substr(i ansLen); } } } return ansLen > 0 ? ans : '-1'; } int main() { string s = 'geeksforgeeks'; cout << longestSubstring(s) << endl; return 0; }
Java // Java program to find longest repeating // and non-overlapping substring // using memoization import java.util.Arrays; class GfG { static int findSuffix(int i int j String s int[][] memo) { // base case if (j == s.length()) return 0; // return memoized value if (memo[i][j] != -1) return memo[i][j]; // if characters match if (s.charAt(i) == s.charAt(j)) { memo[i][j] = 1 + Math.min(findSuffix(i + 1 j + 1 s memo) j - i - 1); } else { memo[i][j] = 0; } return memo[i][j]; } static String longestSubstring(String s) { int n = s.length(); int[][] memo = new int[n][n]; for (int[] row : memo) { Arrays.fill(row -1); } // find length of non-overlapping // substrings for all pairs (i j) for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { findSuffix(i j s memo); } } String ans = ''; int ansLen = 0; // If length of suffix is greater // than ansLen update ans and ansLen for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (memo[i][j] > ansLen) { ansLen = memo[i][j]; ans = s.substring(i i + ansLen); } } } return ansLen > 0 ? ans : '-1'; } public static void main(String[] args) { String s = 'geeksforgeeks'; System.out.println(longestSubstring(s)); } }
Python # Python program to find longest repeating # and non-overlapping substring # using memoization def findSuffix(i j s memo): # base case if j == len(s): return 0 # return memoized value if memo[i][j] != -1: return memo[i][j] # if characters match if s[i] == s[j]: memo[i][j] = 1 + min(findSuffix(i + 1 j + 1 s memo) j - i - 1) else: memo[i][j] = 0 return memo[i][j] def longestSubstring(s): n = len(s) memo = [[-1] * n for _ in range(n)] # find length of non-overlapping # substrings for all pairs (i j) for i in range(n): for j in range(i + 1 n): findSuffix(i j s memo) ans = '' ansLen = 0 # If length of suffix is greater # than ansLen update ans and ansLen for i in range(n): for j in range(i + 1 n): if memo[i][j] > ansLen: ansLen = memo[i][j] ans = s[i:i + ansLen] if ansLen > 0: return ans return '-1' if __name__ == '__main__': s = 'geeksforgeeks' print(longestSubstring(s))
C# // C# program to find longest repeating // and non-overlapping substring // using memoization using System; class GfG { static int findSuffix(int i int j string s int[ ] memo) { // base case if (j == s.Length) return 0; // return memoized value if (memo[i j] != -1) return memo[i j]; // if characters match if (s[i] == s[j]) { memo[i j] = 1 + Math.Min(findSuffix(i + 1 j + 1 s memo) j - i - 1); } else { memo[i j] = 0; } return memo[i j]; } static string longestSubstring(string s) { int n = s.Length; int[ ] memo = new int[n n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { memo[i j] = -1; } } // find length of non-overlapping // substrings for all pairs (i j) for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { findSuffix(i j s memo); } } string ans = ''; int ansLen = 0; // If length of suffix is greater // than ansLen update ans and ansLen for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (memo[i j] > ansLen) { ansLen = memo[i j]; ans = s.Substring(i ansLen); } } } return ansLen > 0 ? ans : '-1'; } static void Main(string[] args) { string s = 'geeksforgeeks'; Console.WriteLine(longestSubstring(s)); } }
JavaScript // JavaScript program to find longest repeating // and non-overlapping substring // using memoization function findSuffix(i j s memo) { // base case if (j === s.length) return 0; // return memoized value if (memo[i][j] !== -1) return memo[i][j]; // if characters match if (s[i] === s[j]) { memo[i][j] = 1 + Math.min(findSuffix(i + 1 j + 1 s memo) j - i - 1); } else { memo[i][j] = 0; } return memo[i][j]; } function longestSubstring(s) { const n = s.length; const memo = Array.from({length : n} () => Array(n).fill(-1)); // find length of non-overlapping // substrings for all pairs (i j) for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { findSuffix(i j s memo); } } let ans = ''; let ansLen = 0; // If length of suffix is greater // than ansLen update ans and ansLen for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { if (memo[i][j] > ansLen) { ansLen = memo[i][j]; ans = s.substring(i i + ansLen); } } } return ansLen > 0 ? ans : '-1'; } const s = 'geeksforgeeks'; console.log(longestSubstring(s));
Výstup
geeks
Použití DP zdola nahoru (tabulka) – O(n^2) čas a O(n^2) prostor
C++Smyslem je vytvořit 2D matici z velikost (n+1)*(n+1) a vypočítat nejdelší opakující se přípony pro všechny indexy páry (i j) iterativně. Začínáme od konec provázku a pracujte zpět, abyste vyplnili tabulku. Pro každého (i j) -li s[i] == s[j] nastavili jsme přípona[i][j] na min(přípona[i+1][j+1]+1 j-i-1) aby se zabránilo překrývání; jinak přípona[i][j] = 0.
// C++ program to find longest repeating // and non-overlapping substring // using tabulation #include using namespace std; string longestSubstring(string s) { int n = s.length(); vector<vector<int>> dp(n+1 vector<int>(n+1 0)); string ans = ''; int ansLen = 0; // find length of non-overlapping // substrings for all pairs (ij) for (int i=n-1; i>=0; i--) { for (int j=n-1; j>i; j--) { // if characters match set value // and compare with ansLen. if (s[i]==s[j]) { dp[i][j] = 1 + min(dp[i+1][j+1] j-i-1); if (dp[i][j]>=ansLen) { ansLen = dp[i][j]; ans = s.substr(i ansLen); } } } } return ansLen>0?ans:'-1'; } int main() { string s = 'geeksforgeeks'; cout << longestSubstring(s) << endl; return 0; }
Java // Java program to find longest repeating // and non-overlapping substring // using tabulation class GfG { static String longestSubstring(String s) { int n = s.length(); int[][] dp = new int[n + 1][n + 1]; String ans = ''; int ansLen = 0; // find length of non-overlapping // substrings for all pairs (i j) for (int i = n - 1; i >= 0; i--) { for (int j = n - 1; j > i; j--) { // if characters match set value // and compare with ansLen. if (s.charAt(i) == s.charAt(j)) { dp[i][j] = 1 + Math.min(dp[i + 1][j + 1] j - i - 1); if (dp[i][j] >= ansLen) { ansLen = dp[i][j]; ans = s.substring(i i + ansLen); } } } } return ansLen > 0 ? ans : '-1'; } public static void main(String[] args) { String s = 'geeksforgeeks'; System.out.println(longestSubstring(s)); } }
Python # Python program to find longest repeating # and non-overlapping substring # using tabulation def longestSubstring(s): n = len(s) dp = [[0] * (n + 1) for _ in range(n + 1)] ans = '' ansLen = 0 # find length of non-overlapping # substrings for all pairs (i j) for i in range(n - 1 -1 -1): for j in range(n - 1 i -1): # if characters match set value # and compare with ansLen. if s[i] == s[j]: dp[i][j] = 1 + min(dp[i + 1][j + 1] j - i - 1) if dp[i][j] >= ansLen: ansLen = dp[i][j] ans = s[i:i + ansLen] return ans if ansLen > 0 else '-1' if __name__ == '__main__': s = 'geeksforgeeks' print(longestSubstring(s))
C# // C# program to find longest repeating // and non-overlapping substring // using tabulation using System; class GfG { static string longestSubstring(string s) { int n = s.Length; int[] dp = new int[n + 1 n + 1]; string ans = ''; int ansLen = 0; // find length of non-overlapping // substrings for all pairs (i j) for (int i = n - 1; i >= 0; i--) { for (int j = n - 1; j > i; j--) { // if characters match set value // and compare with ansLen. if (s[i] == s[j]) { dp[i j] = 1 + Math.Min(dp[i + 1 j + 1] j - i - 1); if (dp[i j] >= ansLen) { ansLen = dp[i j]; ans = s.Substring(i ansLen); } } } } return ansLen > 0 ? ans : '-1'; } static void Main(string[] args) { string s = 'geeksforgeeks'; Console.WriteLine(longestSubstring(s)); } }
JavaScript // JavaScript program to find longest repeating // and non-overlapping substring // using tabulation function longestSubstring(s) { const n = s.length; const dp = Array.from({ length: n + 1 } () => Array(n + 1).fill(0)); let ans = ''; let ansLen = 0; // find length of non-overlapping // substrings for all pairs (i j) for (let i = n - 1; i >= 0; i--) { for (let j = n - 1; j > i; j--) { // if characters match set value // and compare with ansLen. if (s[i] === s[j]) { dp[i][j] = 1 + Math.min(dp[i + 1][j + 1] j - i - 1); if (dp[i][j] >= ansLen) { ansLen = dp[i][j]; ans = s.substring(i i + ansLen); } } } } return ansLen > 0 ? ans : '-1'; } const s = 'geeksforgeeks'; console.log(longestSubstring(s));
Výstup
geeks
Použití Space Optimized DP – O(n^2) Time a O(n) Space
C++Cílem je použít a jediné 1D pole místo a 2D matice sledováním pouze toho 'další řádek' hodnoty potřebné k výpočtu přípona[i][j]. Protože každá hodnota s přípona[i][j] záleží jen na přípona[i+1][j+1] v řádku níže můžeme udržovat hodnoty předchozího řádku v 1D poli a pro každý řádek je iterativně aktualizovat.
// C++ program to find longest repeating // and non-overlapping substring // using space optimised #include using namespace std; string longestSubstring(string s) { int n = s.length(); vector<int> dp(n+10); string ans = ''; int ansLen = 0; // find length of non-overlapping // substrings for all pairs (ij) for (int i=n-1; i>=0; i--) { for (int j=i; j<n; j++) { // if characters match set value // and compare with ansLen. if (s[i]==s[j]) { dp[j] = 1 + min(dp[j+1] j-i-1); if (dp[j]>=ansLen) { ansLen = dp[j]; ans = s.substr(i ansLen); } } else dp[j] = 0; } } return ansLen>0?ans:'-1'; } int main() { string s = 'geeksforgeeks'; cout << longestSubstring(s) << endl; return 0; }
Java // Java program to find longest repeating // and non-overlapping substring // using space optimised class GfG { static String longestSubstring(String s) { int n = s.length(); int[] dp = new int[n + 1]; String ans = ''; int ansLen = 0; // find length of non-overlapping // substrings for all pairs (i j) for (int i = n - 1; i >= 0; i--) { for (int j = i; j < n; j++) { // if characters match set value // and compare with ansLen. if (s.charAt(i) == s.charAt(j)) { dp[j] = 1 + Math.min(dp[j + 1] j - i - 1); if (dp[j] >= ansLen) { ansLen = dp[j]; ans = s.substring(i i + ansLen); } } else { dp[j] = 0; } } } return ansLen > 0 ? ans : '-1'; } public static void main(String[] args) { String s = 'geeksforgeeks'; System.out.println(longestSubstring(s)); } }
Python # Python program to find longest repeating # and non-overlapping substring # using space optimised def longestSubstring(s): n = len(s) dp = [0] * (n + 1) ans = '' ansLen = 0 # find length of non-overlapping # substrings for all pairs (i j) for i in range(n - 1 -1 -1): for j in range(i n): # if characters match set value # and compare with ansLen. if s[i] == s[j]: dp[j] = 1 + min(dp[j + 1] j - i - 1) if dp[j] >= ansLen: ansLen = dp[j] ans = s[i:i + ansLen] else: dp[j] = 0 return ans if ansLen > 0 else '-1' if __name__ == '__main__': s = 'geeksforgeeks' print(longestSubstring(s))
C# // C# program to find longest repeating // and non-overlapping substring // using space optimised using System; class GfG { static string longestSubstring(string s) { int n = s.Length; int[] dp = new int[n + 1]; string ans = ''; int ansLen = 0; // find length of non-overlapping // substrings for all pairs (i j) for (int i = n - 1; i >= 0; i--) { for (int j = i; j < n; j++) { // if characters match set value // and compare with ansLen. if (s[i] == s[j]) { dp[j] = 1 + Math.Min(dp[j + 1] j - i - 1); if (dp[j] >= ansLen) { ansLen = dp[j]; ans = s.Substring(i ansLen); } } else { dp[j] = 0; } } } return ansLen > 0 ? ans : '-1'; } static void Main(string[] args) { string s = 'geeksforgeeks'; Console.WriteLine(longestSubstring(s)); } }
JavaScript // JavaScript program to find longest repeating // and non-overlapping substring // using space optimised function longestSubstring(s) { const n = s.length; const dp = new Array(n + 1).fill(0); let ans = ''; let ansLen = 0; // find length of non-overlapping // substrings for all pairs (i j) for (let i = n - 1; i >= 0; i--) { for (let j = i; j < n; j++) { // if characters match set value // and compare with ansLen. if (s[i] === s[j]) { dp[j] = 1 + Math.min(dp[j + 1] j - i - 1); if (dp[j] >= ansLen) { ansLen = dp[j]; ans = s.substring(i i + ansLen); } } else { dp[j] = 0; } } } return ansLen > 0 ? ans : '-1'; } const s = 'geeksforgeeks'; console.log(longestSubstring(s));
Výstup
geeks
Související články:
- Nejdelší společný podřetězec