Find palindromic substrings as efficiently as possible I've written a function to calculate all the distinct substrings of a given string, that are palindromes. The string is passed as the argument to the function. For example, the string abba is a palindrome because reversed it is also abba. If the function takes the string aabaa it returns 5, because the distinct substrings are a, aa, aabaa, aba, b.

I've currently made use of two for loops for this to work, however, when the string gets big, it's very inefficient due to the fact it iterates one by one. Any suggestions as to how I can make this significantly more efficient? Recursion maybe?

The function: 

function countPalindromesInString(s) {

    let subStrings = [];

    for (let i = 0; i &lt; s.length; i++) {
      for(let j = 0; j &lt; s.length - i; j++) {
        let subString = s.substring(j, j + i + 1);
        if(subString === subString.split('').reverse().join('') &amp;&amp; !subStrings.includes(subString)) {
          subStrings.push(subString);
        }
      }
    }
    return subStrings.length;
}
You code looks pretty neat, i do not think that using recursion would improve it very much, but i have some minor suggestions;

1) Performance-wise improvements

The only thing that seems odd at first glance is how you reverse the string to compare subString.split('').reverse().join('');

I had to look it up, but i found that the way that you are doing its the right way using In-built functions, and its pretty much good for almost all cases, but if you want to improve a little the performance you could use something like:

function reverse(s) {
  var o = [];
  for (var i = 0, len = s.length; i &lt;= len; i++)
    o.push(s.charAt(len - i));
   return o.join('');
}


Using this function is has an improve in performance over your current implementation.

2) Readability

You could extract your conditional and use it as a function so your intent would be more clear:

let isPalindrome = function (word, words) {
  return word === word.split('').reverse().join('') &amp;&amp; !words.includes(word)
}


and use this function in the conditional as:

if(isPalisdrome(subString, subStrings)) {
          subStrings.push(subString);
 }


3) Conclusion

In the end putting all together the code would be something like:

function reverse(s) {
  var o = [];
  for (var i = 0, len = s.length; i &lt;= len; i++)
   o.push(s.charAt(len - i));
   return o.join('');
}

function isPalindrome(word, words) {
  return word === reverse(word) &amp;&amp; !words.includes(word)
}

function countPalindromesInString(s) {
    let subStrings = [];
    for (let i = 0; i &lt; s.length; i++) {
      for(let j = 0; j &lt; s.length - i; j++) {
        let subString = s.substring(j, j + i + 1);
        if(isPalindrome(subString, subStrings)) {
          subStrings.push(subString);
        }
    }
  }
  return subStrings.length;
}