Palindromic Substrings

LeetCode problem 647. Palindromic Substrings.

## Problem description

Given a string `s`, return *the number of **palindromic substrings** in it*.

A string is a **palindrome** when it reads the same backward as forward.

A **substring** is a contiguous sequence of characters within the string.

Example 1
**Input:** s = "abc"
**Output:** 3
**Explanation:** Three palindromic strings: "a", "b", "c".
Example 2
**Input:** s = "aaa"
**Output:** 6
**Explanation:** Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
Constraints
* `1 <= s.length <= 1000`
* `s` consists of lowercase English letters.

## Problem analysis

We can use Dynamic programming to solve the problem, by finding all the endpoints of the palindromic substrings.

We know that if a string is already a palindrome, then adding the same letter on both ends forms a longer palindrome.

Let `len` be the input string's length. We can create the `isPalindrome` table with `len` rows and `len` columns, in which `isPalindrome[left][right]` will indicate whether `input[left..right]` is a palindrome.

We can start from substrings with length 1, and increase the substring length stepwise until we cover the entire string.

* Base cases:
	+ If substring length is 1, then `isPalindrome[left][right] = true`.
	+ If substring length is 2, then `isPalindrome[left][right] = true` if the two characters are the same, or `false` otherwise.
* Recursive case:
	+ If substring length ≥ 3, then `isPalindrome[left][right] = (input[left] == input[right]) && isPalindrome[left+1][right-1]`.

After computing all the cells in the table, the total number of `true` will be the result.

### Complexity analysis

Let `len` be the input string's length.

Space complexity
We created the `isPalindrome` table with `len` rows and `len` columns, so the space complexity is **O(`len`2)**.
Time complexity
Since the amount of time to compute each cell and add a single value to the result is constant, the total time complexity is **O(`len`2)**.
## Solution

### C++ solution

```
class Solution {
public:
 int countSubstrings(string s) {
 const int len = s.length();
 if (len <= 1) {
 return len;
 }

 // isPalindrome[left][right]: whether s[left..right] is palindrome
 bool isPalindrome[len][len];
 memset(isPalindrome, false, sizeof isPalindrome);

 int result = 0;
 for (int subLen = 1; subLen <= len; ++subLen) {
 for (int left = 0; left <= len - subLen; ++left) {
 int right = left + subLen - 1;

 if (subLen == 1) {
 isPalindrome[left][right] = true;
 }
 else if (subLen == 2) {
 isPalindrome[left][right] = s[left] == s[right];
 }
 else {
 // subLen >= 3
 isPalindrome[left][right] = (s[left] == s[right])
 && isPalindrome[left+1][right-1];
 }
 result += isPalindrome[left][right];
 }
 }
 return result;
 }
};

```

### Java solution

```
class Solution {
 public int countSubstrings(String s) {
 final int len = s.length();
 if (len <= 1) {
 return len;
 }

 // isPalindrome[left][right]: whether s[left..right] is palindrome
 boolean[][] isPalindrome = new boolean[len][len];

 int result = 0;
 for (int subLen = 1; subLen <= len; ++subLen) {
 for (int left = 0; left <= len - subLen; ++left) {
 int right = left + subLen - 1;

 if (subLen == 1) {
 isPalindrome[left][right] = true;
 }
 else if (subLen == 2) {
 isPalindrome[left][right] = s.charAt(left) == s.charAt(right);
 }
 else {
 // subLen >= 3
 isPalindrome[left][right] = (s.charAt(left) == s.charAt(right))
 && isPalindrome[left+1][right-1];
 }
 result += (isPalindrome[left][right] ? 1 : 0);
 }
 }
 return result;
 }
}

```

## See also

* Longest Palindromic Substring
* Longest Palindromic Subsequence