var cases = ['aabcccddeaaa', 'abababcdeee', 'ababcdabcd',
'aabaaabaab', '1', '111222', '123456789', '1234567899'];
var innerCount;
function startsWith(str, start, subStart, subLen) {
var subEnd = subStart + subLen - 1;
while(subStart <= subEnd) {
innerCount++;
if(str[start++] != str[subStart++])
return false;
}
return true;
}
function doCompress(str, maxLen, minIndex, maxIndex) {
var len, sub, i, n;
if(maxIndex - minIndex + 1 < 2)
return str.substring(minIndex, maxIndex + 1);
for(len = maxLen; len > 0; len--) {
for(i = minIndex; i + (len * 2) <= maxIndex + 1; i++) {
if(startsWith(str, i + len, i, len)) {
for(n = i + len * 2; (n + len <= maxIndex + 1) && startsWith(str, n, i, len); n += len);
return (i > minIndex ? doCompress(str, len - 1, minIndex, i - 1) : '') +
str.substr(i, len) +
(n < maxIndex ? doCompress(str, len, n, maxIndex) : '');
}
}
}
return str.substring(minIndex, maxIndex + 1);
}
function compress(str) {
innerCount = 0;
return {
source: str,
result: doCompress(str, (str.length / 2) | 0, 0, str.length - 1),
'n^2': str.length*str.length,
innerCount: innerCount};
}
alert(JSON.stringify(cases.map(compress), null, '\t'));