JS Longest Palindrome Substring (Manacher)

JavaScript resolve longest palindrome substring problem by Manacher algorithm.

by Tinytsunami

HTML

<div id="demo">
  String = <input type="text" /> <button>Process</button>
  <pre>waiting for you input something...</pre>
</div>

CSS

body {
  color: #ffffff;
  background: #20262e;
  font-family: monospace, sans-serif;
}

#demo {
  width: 400px;
  padding: 5px;
}

#demo input {
  color: #ffffff;
  background: #20262e;
  outline: none;
  border: none;
  border-bottom: 1px solid #ffffff;
}

#demo pre {
  width: 400px;
  height: 100px;
  border: solid 1px #ffffff;
  overflow-y: scroll;
}

#demo button {
  color: #ffffff;
  background: #20262e;
  border: 1px solid #ffffff;
  outline: none;
}

#demo button:hover {
  color: #20262e;
  background: #ffffff;
  border: 1px solid #ffffff;
}

JavaScript

(function() {
  /* get elements */
  let root = document.getElementById("demo");
  let inputNode = root.getElementsByTagName("input")[0];
  let buttonNode = root.getElementsByTagName("button")[0];
  let outputNode = root.getElementsByTagName("pre")[0];

  /* evaluation time for functions */
  let evaluationTime = function(f, callback) {
    let start = Date.now();
    let value = f();
    callback.call(this, value, (Date.now() - start));
  };

  /* get LPS by exhaustive */
  let main = function(text) {
    let s = text; // change origin string
    let i, j; // palindrome right, left index
    let k = 0; // palindrome center
    let p; // palindrome array
    let m = 0; // protected range

    s = `#${s.split('').join('#')}#`;
		p = Array.from({length: s.length}, function() {return 0;});
    
    // main process
    for (i = 0; i < p.length; i++) {
      j = 2 * k - i;
      if (i + p[j] < m)
        p[i] = p[j];
      else {
        p[i] = m - i;
        while (s[i + p[i]] == s[i - p[i]]) {
          p[i]++;
          if (i + p[i] >= s.length || i - p[i] < 0)
            break; // overflow
        }
        k = i;
        m = k + p[k];
      }
    }
    
    // get answer
    let ans;
    let ansLength, ansIndex;
    let ansStart, ansEnd;
    ansLength = Math.max.apply(this, p);
    ansIndex = p.indexOf(ansLength);
    ansStart = ansIndex - ansLength + 1;
    ansEnd = ansIndex + ansLength;
    ans = s.substring(ansStart, ansEnd).replace(/#/g, '');
    return ans;
  };

  /* user input and process*/
  buttonNode.onclick = function() {
    evaluationTime(function() {
      return main(inputNode.value);
    }, function(LPS, time) {
      if (LPS.length > 30)
        LPS = `${LPS.substr(0, 30)}...`;
      outputNode.innerHTML += `\nLPS = "${LPS}"\nTime = ${time}ms\n`;
      outputNode.scrollTop = outputNode.scrollHeight;
    });
  };
})();