Palindromic Substring

Published: May 30, 2017

We often see problems related to a palindrome or palindromic something. Palindrome is, like “racecar,” a reversed and original are exactly the same string. We see really many types of palindrome related problems. Sometime, problems are based on palindromic substrings. Sometime, those are palindromic subsequences.

The most typical problem is asking the longest palindromic substring or subsequence. However, not just the longest, asking partitions is another popular problem. As for partition problems, palindromes should be substrings. This kind of problems can be solved by a dynamic programming. The dynamic programming solution creates a truthy table which will have trues when the index i to j is a palindrome.

I’m going to write down three types of palindromic substring related problems: the longest, minimum cuts, and printing all palindromic partitions.

Problem Description

Always, a string will be given to this sort of problems, for example, “aabcbd.” That’s it for an input. Then, problems ask what should be found: the longest, min cut (also partitions), print all palindromic partitions, etc. The longest is relatively easy problem since there’s only one the longest palindrome. Theoretically, multiple longests are possible. But, normally if one longest is found, that’s the answer. For example, “aabcbd” is given, the answer is “bcb.”

Min cut is more diffucult. It requires an optimal partitioning. Since a length one string is a palindrome, [a | a | b | c | b | d] (5 cuts) is one of the partitioning based on palindrome. However, it’s obvious 5-cut isn’t the optimal. [aa | bcd | d] (2 cuts) is the answer.

Printing all palindromic partitions is way more difficult. Some solutions don’t take a dynamic programming approach, like in the “Given a string, print all possible palindromic partitions.” When a dynamic approach is chosen, the solution will be two steps.

  1. create a table to find palindromes.
  2. recursively iterate the given string looking at the palindrome table.

The answer for “aabcbd” will be: [[a, a, b, c, b, d], [a, a, bcb, d], [aa, b, c, b, d], [aa, bcb, d]]

The idea to create a truthy table

The truthy table is a key to solve this kind of problems by a dynamic programming. The table saves true/false, whether index i to j is a palindrome or not. Values in the table are so-called, “states,” of the dynamic programming.

The table will be created expanding the range one by one, also shifting the starting index one by one. When filling out the table, a direction is diagonal, from upper left to lower right.


   a a b c b d
   _ _ _ _ _ _
a |\ \ \ \ \ \
a |  \ \ \ \ \
b |    \ \ \ \
c |      \ \ \
b |        \ \
d |          \

Going on by diagonal, i j indices will be incremented with an extra index k. The k expresses a length of substring.

for (int k = 3; k <= n; k++) {
    for (int i = 0; i < n - k + 1; i++) {
        int j = i + k - 1;
	    table[i][j] = ...
    }
}

The way to expand the length and check whether substring is a palindrome or not will be proceeded like this:


    a a b c b d       a a b c b d       a a b c b d       a a b c b d       a a b c b d       a a b c b d
    0 1 2 3 4 5       0 1 2 3 4 5       0 1 2 3 4 5       0 1 2 3 4 5       0 1 2 3 4 5       0 1 2 3 4 5
    _ _ _ _ _ _       _ _ _ _ _ _       _ _ _ _ _ _       _ _ _ _ _ _       _ _ _ _ _ _       - - - - - -
a 0|T             a 0|T T           a 0|T T F         a 0|T T F F       a 0|T T F F F     a 0|T T F F F F
a 1|  T           a 1|  T F         a 1|  T F F       a 1|  T F F F     a 1|  T F F F F   a 1|  T F F F F
b 2|    T         b 2|    T F       b 2|    T F T     b 2|    T F F F   b 2|    T F T F   b 2|    T F T F
c 3|      T       c 3|      T F     c 3|      T F F   c 3|      T F F   c 3|      T F F   c 3|      T F F
b 4|        T     b 4|        T F   b 4|        T F   b 4|        T F   b 4|        T F   b 4|        T F
ff5|          T   d 5|          T   d 5|          T   d 5|          T   d 5|          T   d 5|          T

The logic to check whether the substring from index i to j is a palindrome or not is:

  1. if characters at index i and j are the same,
  2. if a previous state (saved at index i + 1 and j - 1) is true,
  3. the position at index i and j will be true.

The idea to find the longest

The table saves whether the substring of index i to j is a palindrome or not. Given that, when the value is true, i - j + 1 is the length of palindrome. Checking all true positions and compare the length will give me the answer.

The idea to find minimum cuts

The same as the longest problem, minimum cuts sees the table. The cuts happens when the last character of the substring doesn’t form the palindrome. Otherwise, the boundary should be expanded one by one.

The idea to print all palindromic substrings

Likewise, looking at table, adds palindrome one by one, shifting the starting index. In this case, depth first search by recursion will be a good way to find palindromes from the rest of the substring.

Java code

Below is the Java code to find means anytime.

The result is:

longest: aa
min cuts: 1
all: [[a, a, b], [aa, b]]
longest: bcb
min cuts: 2
all: [[a, a, b, c, b, d], [a, a, bcb, d], [aa, b, c, b, d], [aa, bcb, d]]

Resources

Latest Posts

Application Development by Rails Action Cable

The previous two blog posts introduced WebSocket and how to implement a WebSocket application on Ruby on Rails. This blog post digs deeper. It is a memo on creating a more realistic application by Action Cable.

Real-time App on Rails by Action Cable

The previous blog post, WebSocket on Rails by Action Cable, focused on WebSocket as a protocol. As in the previous post, by default, Rails app responds to WebSocket connection requests without any hassle. However, other than connecting and sending ping frames, it doesn’t do anything. This blog post focuses on an application side and explains how we can create a full-duplex, bidirectional app.

WebSocket on Rails by Action Cable

In the web application domain, we hear some protocol names. Absolutely, HTTP or HTTPS is the most famous protocol that all web developers know. Although there’s a mechanism of Keep-Alive, a single request/response sequence with a single client/server is all done by HTTP. The client initiates the HTTP request to the server. Once the client receives the HTTP response from the server, communication finishes. As far as HTTP is used, the server just waits and waits. Only when the request comes in, the server can send back some data to the client. This communication style is surprisingly capable of doing many things, so most web applications are satisfied with HTTP.