// Problema: Longest Repeating Substring
// Descripcion: Encontrar en una cadena de texto la subcadena de texto mas larga que se repite mas de 1 vez
// Juez Virtual: https://c...content-available-to-author-only...s.fi/problemset/task/2106
#include <bits/stdc++.h>
using namespace std;
// Construcción del Suffix Array usando el algoritmo de doubling O(n log² n)
// (versión con sort en lugar de counting sort)
vector<int> construct_suffix_array(string s) {
s += "$"; // Agregamos un carácter centinela menor que cualquier otro
int n = s.length();
vector<int> suffix_array(n);
// Inicialmente, los sufijos se ordenan por su primer carácter
for (int i = 0; i < n; i++) {
suffix_array[i] = n - i - 1;
}
// Orden estable por el primer carácter
stable_sort(suffix_array.begin(), suffix_array.end(), [&] (int i, int j) {
return s[i] < s[j];
});
// Asignamos clases (rank) según el carácter inicial
vector<int> rank(n);
rank[suffix_array[0]] = 0;
for (int i = 1; i < n; i++) {
if (s[suffix_array[i]] != s[suffix_array[i - 1]]) {
rank[suffix_array[i]] = rank[suffix_array[i - 1]] + 1;
}
else {
rank[suffix_array[i]] = rank[suffix_array[i - 1]];
}
}
// Doblamos la longitud del prefijo comparado en cada iteración
for (int k = 0; (1 << k) < n; k++) {
vector<pair<int, int>> pairs(n);
// Cada sufijo se representa por un par (rank actual, rank desplazado)
for (int i = n - 1; i >= 0; i--) {
pairs[i] = {rank[i], rank[(i + (1 << k)) % n]};
}
// Ordenamos según los pares (clave doble)
sort(suffix_array.begin(), suffix_array.end(), [&] (int i, int j) {
return pairs[i] < pairs[j];
});
// Reasignamos los nuevos ranks según el orden obtenido
rank[suffix_array[0]] = 0;
for (int i = 1; i < n; i++) {
if (pairs[suffix_array[i]] != pairs[suffix_array[i - 1]]) {
rank[suffix_array[i]] = rank[suffix_array[i - 1]] + 1;
}
else {
rank[suffix_array[i]] = rank[suffix_array[i - 1]];
}
}
}
// Quitamos la posición del sufijo que empieza con '$'
suffix_array.erase(suffix_array.begin());
return suffix_array;
}
// Construcción del arreglo LCP (Longest Common Prefix) en O(n)
// LCP[i] = longitud del prefijo común entre sufijos SA[i] y SA[i+1]
vector<int> construct_lcp(string& s, vector<int>& suffix_array) {
int n = s.length();
vector<int> lcp(n - 1);
vector<int> rank(n);
// rank[i] = posición del sufijo que empieza en i dentro del SA
for (int i = 0; i < n; i++) {
rank[suffix_array[i]] = i;
}
int k = 0; // longitud actual del prefijo común
for (int i = 0; i < n; i++) {
if (rank[i] == n - 1) {
continue; // último sufijo, no tiene siguiente
}
int j = suffix_array[rank[i] + 1]; // siguiente sufijo en el SA
// Calculamos LCP comparando carácter por carácter
while (i + k < n && j + k < n && s[i + k] == s[j + k]) k++;
lcp[rank[i]] = k; // guardamos el resultado
if (k > 0) k--; // optimización: siguiente comparación empieza con k-1
}
return lcp;
}
int main() {
cin.tie(0);
ios_base::sync_with_stdio(0);
string s;
cin >> s;
int n = s.length();
// Caso trivial: solo un carácter, no hay repeticiones
if (n == 1) {
cout << -1 << endl;
exit(0);
}
// Construimos el SA y el arreglo LCP
vector<int> suffix_array = construct_suffix_array(s);
vector<int> lcp = construct_lcp(s, suffix_array);
// Buscamos el valor máximo del LCP (la subcadena repetida más larga)
int mx = *max_element(lcp.begin(), lcp.end());
int ind = 0;
while (lcp[ind] != mx) ind++;
// Si no hay repeticiones, imprimimos -1
if (mx == 0) {
cout << -1 << endl;
exit(0);
}
// Imprimimos la subcadena repetida más larga
for (int i = 0; i < mx; i++) {
cout << s[suffix_array[ind] + i];
}
cout << endl;
}