Cadeia máxima de prefixo do produto

A seguir, uma pergunta demo de um site de entrevista de codificação chamado codility:

Um prefixo de uma string S é qualquer parte contígua inicial de S. Por exemplo, "c" e "cod" são prefixos da string "codility". Para simplificar, exigimos que os prefixos não estejam vazios.

O produto do prefixo P da string S é o número de ocorrências de P multiplicado pelo comprimento de P. Mais precisamente, se o prefixo P consistir em K caracteres e P ocorrer exatamente T vezes em S, o produto será igual a K * T.

Por exemplo, S = "abababa" possui os seguintes prefixos:

"a", cujo produto é igual a 1 * 4 = 4,"ab", cujo produto é igual a 2 * 3 = 6,"aba", cujo produto é igual a 3 * 3 = 9,"abab", cujo produto é igual a 4 * 2 = 8,"ababa", cujo produto é igual a 5 * 2 = 10,"ababab", cujo produto é igual a 6 * 1 = 6,"abababa", cujo produto é igual a 7 * 1 = 7.

O prefixo mais longo é idêntico à sequência original. O objetivo é escolher um prefixo que maximize o valor do produto. No exemplo acima, o produto máximo é 10.

Abaixo está minha solução ruim em Java, exigindo tempo O (N ^ 2). Aparentemente, é possível fazer isso em O (N). Eu estava pensando no algoritmo Kadanes. Mas não consigo pensar em nenhuma maneira de codificar algumas informações a cada etapa que me permitam encontrar o máximo em execução. Alguém pode pensar em um algoritmo O (N) para isso?

import java.util.HashMap;

class Solution {
    public int solution(String S) {
        int N = S.length();
        if(N<1 || N>300000){
            System.out.println("Invalid length");
            return(-1);
        }
        HashMap<String,Integer> prefixes = new HashMap<String,Integer>();
        for(int i=0; i<N; i++){
            String keystr = "";
            for(int j=i; j>=0; j--) {
                keystr += S.charAt(j);
                if(!prefixes.containsKey(keystr))
                    prefixes.put(keystr,keystr.length());
                else{
                    int newval = prefixes.get(keystr)+keystr.length();
                    if(newval > 1000000000)return 1000000000;
                    prefixes.put(keystr,newval);
                }
            }
        }
        int maax1 = 0;
        for(int val : prefixes.values())
            if(val>maax1)
                maax1 = val;
        return maax1;
    }
}

questionAnswers(2)

yourAnswerToTheQuestion