Reputation: 45
I have a programm that can find the longest repeating substring of entered string, but the thing is, when there are 2 repeating substrings of the biggest length in answer I get only one of them.
For instance, for the string 123b456k123m456j the answer is 123, while answer 123 and 456 is expected..
Can I somehow fix this problem? If you know how, please answer my question))
let s = prompt('Enter string');
function substr(str, begin, end) {
let result = "";
for (let i = begin; i < end; i++) {
result += str[i];
}
return result;
}
function lcp(str1, str2) {
let n = Math.min(str1.length, str2.length);
for (let i = 0; i < n; i++) {
if (str1.charAt(i) != str2.charAt(i)) {
return substr(str1, 0, i);
}
}
return substr(str1, 0, n);
}
function lrs(str) {
const suffixes = [];
for (let i = 0; i < str.length; i++) {
suffixes.push(substr(str, i, str.length));
}
suffixes.sort();
let result = '';
let res=[];
for (let i = 0; i < str.length - 1; i++) {
const p = lcp(suffixes[i], suffixes[i + 1]);
if (p.length > result.length){
result = p;
}
}
return result;
}
alert(lrs(s));
Upvotes: 2
Views: 2338
Reputation: 97130
Using String.prototype.match()
and filtering out the shorter matches should get you there:
const lrs = (s) => s.match(/(.+)(?=.*\1)/g)
.filter((x, _, a) => !a.some((y) => x.length < y.length));
console.log(lrs('123b456k123m456j'));
The filter condition using Array.prototype.some()
should be probably swapped out for something with better performance if you expect a large number of matches.
Update
As mentioned in the comments by @cars10m, this produces incorrect results in cases where part of a longer repeating pattern is already consumed by the regex matcher when it matched a shorter repeating pattern.
Solution is to wrap the entire expression into a look-ahead group and advance the regex matcher one character at a time:
const lrs = (s) => [...s.matchAll(/(?=(.+)(?=.*\1))./g)]
.map(([_,v]) => v)
.filter((x, _, a) => !a.some((y) => x.length < y.length));
console.log(lrs('123456k123m3456j'));
Upvotes: 4
Reputation: 1247
Try replacing your function Los with the below.
function lrs(str) {
const suffixes = [];
for (let i = 0; i < str.length; i++) {
suffixes.push(substr(str, i, str.length));
}
suffixes.sort();
let result = [];
let res = [];
let lastLongestSubStrLen = 0;
for (let i = 0; i < str.length - 1; i++) {
const p = lcp(suffixes[i], suffixes[i + 1]);
if (lastLongestSubStrLen <= p.length) {
result.push(p);
lastLongestSubStrLen = p.length;
continue;
}
}
return result;
}
It will work! But, my concern here you have nested loops. We need to optimise that for performance.
Please note you need modify the if
condition I just altered for error handling. Also, I didn't check the worst cases. For eg: the first occurrence of repeated substring is length of 2, and the next once is length of 3, then you might want to clear all the elements before pushing a new one.
Happy Coding!
Upvotes: 0