Вот решение JS с комментарием, в котором используется префиксная функция, о которой DAIe упомянул :
function getPrefixBorders(string) {
// This will contain the border length for each
// prefix in ascending order by prefix length.
var borderLengthByPrefix = [0];
// This is the length of the border on the current prefix.
var curBorderLength = 0;
// Loop from the 2nd character to the last.
for (var i = 1; i < string.length; i++) {
// As long as a border exists but the character
// after it doesn't match the current character,
while (curBorderLength > 0 && string[curBorderLength] !== string[i])
// set the border length to the length of the current border's border.
curBorderLength = borderLengthByPrefix[curBorderLength - 1];
// If the characters do match,
if (string[curBorderLength] === string[i])
// the new border is 1 character longer.
curBorderLength++;
// Note the border length of the current prefix.
borderLengthByPrefix[i] = curBorderLength;
}
return borderLengthByPrefix;
}
Возвращает самую длинную границу каждого префикса в строке (это намного больше, чем запрашивается, но это происходит за линейное время). Таким образом, чтобы получить длину самой длинной границы в полной строке:
var string = "ababab";
var borderLengthsByPrefix = getPrefixBorders(); // [0,0,1,2,3,4]
var stringBorderLength = borderLengthsByPrefix[borderLengthsByPrefix.length - 1];
Еще один отличный ресурс для понимания того, как это работает, - это видео (и то, что перед ним) на Coursera.