logo

המחרוזת החוזרת והלא חופפת הארוכה ביותר

נסה את זה ב-GfG Practice ' title=

בהינתן א מחרוזת s המשימה היא למצוא את המחרוזת החוזרת הארוכה ביותר שאינה חופפת בּוֹ. במילים אחרות למצוא 2 תת מחרוזות זהות שֶׁל אורך מקסימלי שאינם חופפים. החזר -1 אם לא קיימת מחרוזת כזו.

פֶּתֶק:  תשובות מרובות אפשריות אך עלינו להחזיר את מחרוזת משנה שֶׁל מִי  התרחשות ראשונה מוקדם יותר.

דוגמאות:  



קֶלֶט:  s = 'acdcdcdc'
תְפוּקָה: 'AC/DC'
הֶסבֵּר: המחרוזת 'acdc' היא המחרוזת המשנה הארוכה ביותר של s שחוזרת על עצמה אך אינה חופפת.

קֶלֶט: s = 'חנונים'
תְפוּקָה: 'חנונים'
הֶסבֵּר: המחרוזת 'גיקים' היא תת המחרוזת הארוכה ביותר של s שחוזרת על עצמה אך אינה חופפת.

תוכן עניינים

שימוש בשיטת כוח גס - O(n^3) זמן ו-O(n) מרחב

הרעיון הוא לִיצוֹר כל ה מחרוזות משנה אפשריות ובדוק אם המחרוזת המשנה קיימת ב- נוֹתָר חוּט. אם תת-מחרוזת קיימת והיא מֶשֶׁך הוא גדול יותר מאשר מחרוזת המשנה ואז הגדר תְשׁוּבָה למחרוזת המשנה הנוכחית.

C++
// 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)); 

תְפוּקָה
geeks 

שימוש ב-Top-Down DP (Memoization) - O(n^2) זמן ו-O(n^2) Space

הגישה היא לחשב את הסיומת החוזרת הארוכה ביותר עבור כל הקידומת זוגות ב מחרוזת s . עבור מדדים אֲנִי ו י אִם s[i] == s[j] אָז באופן רקורסיבי לְחַשֵׁב סיומת (i+1 j+1) וקבע סיומת (i j) כְּמוֹ min(סיומת(i+1 j+1) + 1 j - i - 1) אֶל למנוע חפיפה . אם הדמויות אינן תואמות set suffix(i j) = 0.

פֶּתֶק:

  • כדי למנוע חפיפה עלינו להבטיח כי האורך של הסיומת קטנה מ-(j-i) בכל רגע. 
  • הערך המקסימלי של סיומת (i j) מספק את האורך של המחרוזת החוזרת הארוכה ביותר וניתן למצוא את המחרוזת עצמה באמצעות האורך והאינדקס ההתחלתי של הסיומת המשותפת.
  • סיומת (i j) מאחסן את אורך הסיומת הנפוצה הארוכה ביותר בין מדדים אני ו-j להבטיח את זה אינו עולה על j - i - 1 כדי למנוע חפיפה.
C++
// 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)); 

תְפוּקָה
geeks 

שימוש ב- DP מלמטה למעלה (טבלה) - O(n^2) זמן ו-O(n^2) מרחב

הרעיון הוא ליצור מטריצה ​​דו מימדית שֶׁל גודל (n+1)*(n+1) וחשב את הסיומות החוזרות והארוכות ביותר עבור כל המדדים זוגות (i j) באופן איטרטיבי. אנחנו מתחילים מה סוֹף של החוט ועבוד לאחור כדי למלא את הטבלה. לכל אחד (i j) אִם s[i] == s[j] אנחנו קובעים סיומת[i][j] ל-min(סיומת[i+1][j+1]+1 j-i-1) כדי למנוע חפיפה; אַחֶרֶת סיומת[i][j] = 0.

C++
// 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)); 

תְפוּקָה
geeks 

שימוש ב-Space Optimized DP – O(n^2) זמן ו-O(n) Space

הרעיון הוא להשתמש ב- a מערך 1D יחיד במקום א מטריצה ​​דו מימדית על ידי מעקב אחר רק את 'השורה הבאה' ערכים הנדרשים לחישוב סיומת [i][j]. מאז כל ערך s uffix[i][j] תלוי רק ב סיומת[i+1][j+1] בשורה למטה נוכל לשמור את ערכי השורה הקודמת במערך 1D ולעדכן אותם באופן איטרטיבי עבור כל שורה.

C++
// 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)); 

תְפוּקָה
geeks 

מאמרים קשורים: 

  • המחרוזת המשותפת הנפוצה הארוכה ביותר