БлогNot. Самая длинная повторяющаяся без пересечений подстрока в строке

Самая длинная повторяющаяся без пересечений подстрока в строке

Например, "abra" в "abracadabra", "колокол" в "около колокола околачивались колокольчики", "3" в "333" (иначе будет самопересечение) или пустая в "12345".

Само решение имеет сложность по времени O(N2) - а как меньше? - и использует дополнительную целочисленную таблицу Table размерностью (n+1)x(n+1) при длине строки n символов. Значение Table[i][j] хранит длину совпадающих и не пересекающихся подстрок, ограниченных символами с номерами i и j.

Ниже показан листинг, проверенный в консоли Studio 2019.

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

string longestSubstring(string str) {
 int n = str.length();
 int **Table = new int * [n+1];
 if (!Table) return NULL;
 for (int k=0; k<n+1; k++) {
  Table[k] = new int [n+1];
  if (!Table[k]) return NULL;
  for (int j=0; j<n+1; j++) Table[k][j] = 0;
 }
 string res = ""; int res_length = 0; //строка с результатом и ее длина
 int i, index = 0;
 for (i = 1; i <= n; i++) {
  for (int j = i + 1; j <= n; j++)  {
   if (str[i - 1] == str[j - 1] && Table[i - 1][j - 1] < (j - i)) {
    Table[i][j] = Table[i - 1][j - 1] + 1;
    if (Table[i][j] > res_length) {
     res_length = Table[i][j];
     index = max(i, index);
    }
   }
   else
   Table[i][j] = 0;
  }
 }
 if (res_length > 0)
  for (i = index - res_length + 1; i <= index; i++)
   res.push_back (str[i - 1]);
 for (int k = n; k > -1; k--) delete Table[k];
 delete Table;
 return res;
}
 
int main() {
 string str = "okolokolokolakolokolilosololo";
 string res = longestSubstring(str);
 cout << "Answer is: " << res << ", length = " << res.length();
 cin.get();
 return 0;
}

теги: c++ textprocessing алгоритм

08.12.2019, 13:18; рейтинг: 209