All distinct palindromic sub-strings of a given string
Last Updated :
04 Aug, 2025
Given a string s of lowercase English letters. Find all the distinct continuous palindromic sub-strings which are present in the string s.
Examples:
Input: s = "abaaa"
Output: [ "a", "aa", "aaa", "aba", "b" ]
Explanation: All 5 distinct continuous palindromic sub-strings are listed above.
Input: s = "geek"
Output: [ "e", "ee", "g", "k" ]
Explanation: All 4 distinct continuous palindromic sub-strings are listed above.
[Naive Approach] Generating All Substrings - O(n^3 × log n)
The idea is to generate all possible substrings and find all the palindromic substrings, and use set to store all the distinct one.
C++
#include <iostream>
#include <string>
#include <vector>
#include <set>
using namespace std;
vector<string> palindromicSubstr(string &s) {
int n = s.length();
set<string> result;
// generate all substrings
for(int i = 0; i < n; i++) {
// to store the substring
string cur = "";
for(int j = i; j < n; j++) {
cur += s[j];
// check if cur is palindrome
int l = 0, r = cur.length() - 1;
bool isPalindrome = true;
while(l < r) {
if(cur[l] != cur[r]) {
isPalindrome = false;
break;
}
l++;
r--;
}
// if cur is palindrome, insert it into the set
if(isPalindrome) {
result.insert(cur);
}
}
}
// Convert the set to a vector
vector<string> res(result.begin(), result.end());
return res;
}
int main() {
string s = "abaaa";
vector<string> result = palindromicSubstr(s);
for(string s1 : result)
cout << s1 << " ";
return 0;
}
Java
import java.util.Set;
import java.util.ArrayList;
import java.util.TreeSet;
public class GfG {
public static ArrayList<String> palindromicSubstr(String s) {
int n = s.length();
// use TreeSet instead of HashSet to store sorted unique palindromic substrings
Set<String> result = new TreeSet<>();
// generate all substrings
for (int i = 0; i < n; i++) {
// to store the substring
String cur = "";
for (int j = i; j < n; j++) {
cur += s.charAt(j);
// check if cur is palindrome
int l = 0, r = cur.length() - 1;
boolean isPalindrome = true;
while (l < r) {
if (cur.charAt(l) != cur.charAt(r)) {
isPalindrome = false;
break;
}
l++;
r--;
}
// if cur is palindrome, insert it into the set
if (isPalindrome) {
result.add(cur);
}
}
}
// convert set to ArrayList
return new ArrayList<>(result);
}
public static void main(String[] args) {
String s = "abaaa";
ArrayList<String> result = palindromicSubstr(s);
for (String s1 : result)
System.out.print(s1 + " ");
}
}
Python
def palindromicSubstr(s):
n = len(s)
# use set to store sorted unique
# palindromic substrings
result = set()
# generate all substrings
for i in range(n):
# to store the substring
cur = ""
for j in range(i, n):
cur += s[j]
# check if cur is palindrome
l, r = 0, len(cur) - 1
is_palindrome = True
while l < r:
if cur[l] != cur[r]:
is_palindrome = False
break
l += 1
r -= 1
# if cur is palindrome, insert it into
# the set
if is_palindrome:
result.add(cur)
# convert set to sorted list
res = sorted(result)
return res
if __name__ == "__main__":
s = "abaaa"
result = palindromicSubstr(s)
for s1 in result:
print(s1, end=" ")
C#
using System;
using System.Collections.Generic;
class GfG {
public static List<string> palindromicSubstr(string s) {
int n = s.Length;
// use SortedSet to store sorted unique
// palindromic substrings
SortedSet<string> result =
new SortedSet<string>();
// generate all substrings
for (int i = 0; i < n; i++) {
// to store the substring
string cur = "";
for (int j = i; j < n; j++) {
cur += s[j];
// check if cur is palindrome
int l = 0, r = cur.Length - 1;
bool isPalindrome = true;
while (l < r) {
if (cur[l] != cur[r]) {
isPalindrome = false;
break;
}
l++;
r--;
}
// if cur is palindrome, insert it
// into the set
if (isPalindrome) {
result.Add(cur);
}
}
}
// convert set to list
return new List<string>(result);
}
static void Main() {
string s = "abaaa";
List<string> result = palindromicSubstr(s);
foreach (string s1 in result)
Console.Write(s1 + " ");
}
}
JavaScript
function palindromicSubstr(s) {
const n = s.length;
// use Set to store unique palindromic substrings
const result = new Set();
// generate all substrings
for (let i = 0; i < n; i++) {
// to store the substring
let cur = "";
for (let j = i; j < n; j++) {
cur += s[j];
// check if cur is palindrome
let l = 0, r = cur.length - 1;
let isPalindrome = true;
while (l < r) {
if (cur[l] !== cur[r]) {
isPalindrome = false;
break;
}
l++;
r--;
}
// if cur is palindrome, insert it into the set
if (isPalindrome) {
result.add(cur);
}
}
}
// convert set to sorted array
const res = Array.from(result).sort();
return res;
}
// Driver Code
const s = "abaaa";
const result = palindromicSubstr(s);
for (const s1 of result) {
process.stdout.write(s1 + " ");
}
[Better Approach] Using Rabin Karp and Center Expansion
The idea in this approach is to find all unique palindromic substrings in a given string using Rabin-Karp double hashing for fast substring comparison.
We expand around each character (odd length) and each pair (even length) to check for palindromes. For every palindrome found, we compute its double hash and store it in a set to ensure uniqueness.
We also mark its position using a 2D mark array. Finally, we extract all marked substrings and return them. This avoids using a set of strings and ensures efficient comparison using only integer hashes.
C++
#include <iostream>
#include <string>
#include <vector>
#include <set>
using namespace std;
class RabinKarpHash {
private:
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
const int base1 = 31;
const int base2 = 37;
vector<int> hash1, hash2;
vector<int> power1, power2;
// modular addition
int add(int a, int b, int mod) {
a += b;
if (a >= mod) a -= mod;
return a;
}
// modular subtraction
int sub(int a, int b, int mod) {
a -= b;
if (a < 0) a += mod;
return a;
}
// modular multiplication
int mul(int a, int b, int mod) {
return (int)((1LL * a * b) % mod);
}
// convert character to int
int charToInt(char c) {
return c - 'a' + 1;
}
public:
// constructor: precomputes both prefix hashes and powers
RabinKarpHash(string &s) {
int n = s.size();
hash1.resize(n);
hash2.resize(n);
power1.resize(n);
power2.resize(n);
hash1[0] = charToInt(s[0]);
hash2[0] = charToInt(s[0]);
power1[0] = 1;
power2[0] = 1;
for (int i = 1; i < n; ++i) {
hash1[i] = add(mul(hash1[i - 1], base1, mod1),
charToInt(s[i]), mod1);
power1[i] = mul(power1[i - 1], base1, mod1);
hash2[i] = add(mul(hash2[i - 1], base2, mod2),
charToInt(s[i]), mod2);
power2[i] = mul(power2[i - 1], base2, mod2);
}
}
// get double hash of substring s[l...r]
vector<int> getSubHash(int l, int r) {
int h1 = hash1[r];
int h2 = hash2[r];
if (l > 0) {
h1 = sub(h1, mul(hash1[l - 1], power1[r - l + 1], mod1), mod1);
h2 = sub(h2, mul(hash2[l - 1], power2[r - l + 1], mod2), mod2);
}
return {h1, h2};
}
};
vector<string> palindromicSubstr(string &s) {
RabinKarpHash rb(s);
int n = s.length();
// create a set to store the result
set<vector<int>> disPalin;
vector<vector<bool>> mark(n, vector<bool> (n, false));
// check for odd length palindromes
for (int i = 0; i < n; i++) {
int left = i, right = i;
while (left >= 0 && right < n && s[left] == s[right]) {
// add the palindrome substring
vector<int> hashleftright = rb.getSubHash(left, right);
if(disPalin.find(hashleftright) == disPalin.end()){
disPalin.insert(hashleftright);
mark[left][right] = true;
}
left--;
right++;
}
}
// check for even length palindromes
for (int i = 0; i < n - 1; i++) {
int left = i, right = i + 1;
while (left >= 0 && right < n && s[left] == s[right]) {
// add the palindrome substring
vector<int> hashleftright = rb.getSubHash(left, right);
if(disPalin.find(hashleftright) == disPalin.end()){
disPalin.insert(hashleftright);
mark[left][right] = true;
}
left--;
right++;
}
}
vector<string> res;
for(int i = 0; i < n ; i++){
string sub = "";
for(int j = i ; j < n ; j++){
sub.push_back(s[j]);
if(mark[i][j] == true){
res.push_back(sub);
}
}
}
return res;
}
int main() {
string s = "abaaa";
vector<string> result = palindromicSubstr(s);
for(string str : result)
cout << str << " ";
return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class RabinKarpHash {
private final int mod1 = (int)1e9 + 7;
private final int mod2 = (int)1e9 + 9;
private final int base1 = 31;
private final int base2 = 37;
private int[] hash1, hash2;
private int[] power1, power2;
// modular addition
int add(int a, int b, int mod) {
a += b;
if (a >= mod) a -= mod;
return a;
}
// modular subtraction
int sub(int a, int b, int mod) {
a -= b;
if (a < 0) a += mod;
return a;
}
// modular multiplication
int mul(int a, int b, int mod) {
return (int)(((long)a * b) % mod);
}
// convert character to int
int charToInt(char c) {
return c - 'a' + 1;
}
// constructor: precomputes both prefix hashes and powers
public RabinKarpHash(String s) {
int n = s.length();
hash1 = new int[n];
hash2 = new int[n];
power1 = new int[n];
power2 = new int[n];
hash1[0] = charToInt(s.charAt(0));
hash2[0] = charToInt(s.charAt(0));
power1[0] = 1;
power2[0] = 1;
for (int i = 1; i < n; ++i) {
hash1[i] = add(mul(hash1[i - 1], base1, mod1), charToInt(s.charAt(i)), mod1);
power1[i] = mul(power1[i - 1], base1, mod1);
hash2[i] = add(mul(hash2[i - 1], base2, mod2), charToInt(s.charAt(i)), mod2);
power2[i] = mul(power2[i - 1], base2, mod2);
}
}
// get double hash of substring s[l...r]
public List<Integer> getSubHash(int l, int r) {
int h1 = hash1[r];
int h2 = hash2[r];
if (l > 0) {
h1 = sub(h1, mul(hash1[l - 1], power1[r - l + 1], mod1), mod1);
h2 = sub(h2, mul(hash2[l - 1], power2[r - l + 1], mod2), mod2);
}
return Arrays.asList(h1, h2);
}
}
class GfG {
public static ArrayList<String> palindromicSubstr(String s) {
RabinKarpHash rb = new RabinKarpHash(s);
int n = s.length();
// create a set to store the result
Set<List<Integer>> disPalin = new HashSet<>();
boolean[][] mark = new boolean[n][n];
// check for odd length palindromes
for (int i = 0; i < n; i++) {
int left = i, right = i;
while (left >= 0 && right < n && s.charAt(left) == s.charAt(right)) {
// add the palindrome substring
List<Integer> hashleftright = rb.getSubHash(left, right);
if (!disPalin.contains(hashleftright)) {
disPalin.add(hashleftright);
mark[left][right] = true;
}
left--;
right++;
}
}
// check for even length palindromes
for (int i = 0; i < n - 1; i++) {
int left = i, right = i + 1;
while (left >= 0 && right < n && s.charAt(left) == s.charAt(right)) {
// add the palindrome substring
List<Integer> hashleftright = rb.getSubHash(left, right);
if (!disPalin.contains(hashleftright)) {
disPalin.add(hashleftright);
mark[left][right] = true;
}
left--;
right++;
}
}
ArrayList<String> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
StringBuilder sub = new StringBuilder();
for (int j = i; j < n; j++) {
sub.append(s.charAt(j));
if (mark[i][j]) {
res.add(sub.toString());
}
}
}
return res;
}
public static void main(String[] args) {
String s = "abaaa";
ArrayList<String> result = palindromicSubstr(s);
for (String str : result) {
System.out.print(str + " ");
}
}
}
Python
# Rabin-Karp hash class
class RabinKarpHash:
def __init__(self, s):
self.mod1 = 10**9 + 7
self.mod2 = 10**9 + 9
self.base1 = 31
self.base2 = 37
n = len(s)
self.hash1 = [0] * n
self.hash2 = [0] * n
self.power1 = [0] * n
self.power2 = [0] * n
self.hash1[0] = self.charToInt(s[0])
self.hash2[0] = self.charToInt(s[0])
self.power1[0] = 1
self.power2[0] = 1
for i in range(1, n):
self.hash1[i] = self.add(self.mul(self.hash1[i-1], self.base1, self.mod1), \
self.charToInt(s[i]), self.mod1)
self.power1[i] = self.mul(self.power1[i-1], self.base1, self.mod1)
self.hash2[i] = self.add(self.mul(self.hash2[i-1], self.base2, self.mod2), \
self.charToInt(s[i]), self.mod2)
self.power2[i] = self.mul(self.power2[i-1], self.base2, self.mod2)
# modular addition
def add(self, a, b, mod):
a += b
if a >= mod:
a -= mod
return a
# modular subtraction
def sub(self, a, b, mod):
a -= b
if a < 0:
a += mod
return a
# modular multiplication
def mul(self, a, b, mod):
return (a * b) % mod
# convert character to int
def charToInt(self, c):
return ord(c) - ord('a') + 1
# get double hash of substring s[l...r]
def getSubHash(self, l, r):
h1 = self.hash1[r]
h2 = self.hash2[r]
if l > 0:
h1 = self.sub(h1, self.mul(self.hash1[l-1], \
self.power1[r-l+1], self.mod1), self.mod1)
h2 = self.sub(h2, self.mul(self.hash2[l-1], \
self.power2[r-l+1], self.mod2), self.mod2)
return (h1, h2)
# main logic
def palindromicSubstr(s):
rb = RabinKarpHash(s)
n = len(s)
# create a set to store the result
disPalin = set()
mark = [[False] * n for _ in range(n)]
# check for odd length palindromes
for i in range(n):
left = i
right = i
while left >= 0 and right < n and s[left] == s[right]:
hashleftright = rb.getSubHash(left, right)
if hashleftright not in disPalin:
disPalin.add(hashleftright)
mark[left][right] = True
left -= 1
right += 1
# check for even length palindromes
for i in range(n - 1):
left = i
right = i + 1
while left >= 0 and right < n and s[left] == s[right]:
hashleftright = rb.getSubHash(left, right)
if hashleftright not in disPalin:
disPalin.add(hashleftright)
mark[left][right] = True
left -= 1
right += 1
res = []
for i in range(n):
sub = ""
for j in range(i, n):
sub += s[j]
if mark[i][j]:
res.append(sub)
return res
if __name__ == "__main__":
s = "abaaa"
result = palindromicSubstr(s)
print(" ".join(result))
C#
using System;
using System.Collections.Generic;
class RabinKarpHash {
private readonly int mod1 = 1000000007;
private readonly int mod2 = 1000000009;
private readonly int base1 = 31;
private readonly int base2 = 37;
private List<int> hash1, hash2;
private List<int> power1, power2;
// modular addition
private int add(int a, int b, int mod) {
a += b;
if (a >= mod) a -= mod;
return a;
}
// modular subtraction
private int sub(int a, int b, int mod) {
a -= b;
if (a < 0) a += mod;
return a;
}
// modular multiplication
private int mul(int a, int b, int mod) {
return (int)(((long)a * b) % mod);
}
// convert character to int
private int charToInt(char c) {
return c - 'a' + 1;
}
// constructor: precomputes both prefix hashes and powers
public RabinKarpHash(string s) {
int n = s.Length;
hash1 = new List<int>(new int[n]);
hash2 = new List<int>(new int[n]);
power1 = new List<int>(new int[n]);
power2 = new List<int>(new int[n]);
hash1[0] = charToInt(s[0]);
hash2[0] = charToInt(s[0]);
power1[0] = 1;
power2[0] = 1;
for (int i = 1; i < n; ++i) {
hash1[i] = add(mul(hash1[i - 1], base1, mod1), charToInt(s[i]), mod1);
power1[i] = mul(power1[i - 1], base1, mod1);
hash2[i] = add(mul(hash2[i - 1], base2, mod2), charToInt(s[i]), mod2);
power2[i] = mul(power2[i - 1], base2, mod2);
}
}
// get double hash of substring s[l...r]
public Tuple<int, int> getSubHash(int l, int r) {
int h1 = hash1[r];
int h2 = hash2[r];
if (l > 0)
{
h1 = sub(h1, mul(hash1[l - 1], power1[r - l + 1], mod1), mod1);
h2 = sub(h2, mul(hash2[l - 1], power2[r - l + 1], mod2), mod2);
}
return Tuple.Create(h1, h2);
}
}
class GfG {
public static List<string> palindromicSubstr(string s) {
RabinKarpHash rb = new RabinKarpHash(s);
int n = s.Length;
// create a set to store the result
HashSet<string> disPalinSet = new HashSet<string>();
bool[,] mark = new bool[n, n];
// check for odd length palindromes
for (int i = 0; i < n; i++) {
int left = i, right = i;
while (left >= 0 && right < n && s[left] == s[right]) {
var hashleftright = rb.getSubHash(left, right);
string key = hashleftright.Item1 + "#" + hashleftright.Item2;
if (!disPalinSet.Contains(key))
{
disPalinSet.Add(key);
mark[left, right] = true;
}
left--;
right++;
}
}
// check for even length palindromes
for (int i = 0; i < n - 1; i++) {
int left = i, right = i + 1;
while (left >= 0 && right < n && s[left] == s[right]) {
var hashleftright = rb.getSubHash(left, right);
string key = hashleftright.Item1 + "#" + hashleftright.Item2;
if (!disPalinSet.Contains(key))
{
disPalinSet.Add(key);
mark[left, right] = true;
}
left--;
right++;
}
}
List<string> res = new List<string>();
for (int i = 0; i < n; i++) {
string sub = "";
for (int j = i; j < n; j++)
{
sub += s[j];
if (mark[i, j])
{
res.Add(sub);
}
}
}
return res;
}
// Driver Code
public static void Main() {
string s = "abaaa";
List<string> result = palindromicSubstr(s);
foreach (string str in result) {
Console.Write(str + " ");
}
}
}
JavaScript
function RabinKarpHash(s) {
this.mod1 = 1e9 + 7;
this.mod2 = 1e9 + 9;
this.base1 = 31;
this.base2 = 37;
this.hash1 = new Array(s.length).fill(0);
this.hash2 = new Array(s.length).fill(0);
this.power1 = new Array(s.length).fill(0);
this.power2 = new Array(s.length).fill(0);
const charToInt = c => c.charCodeAt(0) - 'a'.charCodeAt(0) + 1;
this.hash1[0] = charToInt(s[0]);
this.hash2[0] = charToInt(s[0]);
this.power1[0] = 1;
this.power2[0] = 1;
for (let i = 1; i < s.length; i++) {
this.hash1[i] = this.add(this.mul(this.hash1[i - 1], this.base1, this.mod1), charToInt(s[i]), this.mod1);
this.power1[i] = this.mul(this.power1[i - 1], this.base1, this.mod1);
this.hash2[i] = this.add(this.mul(this.hash2[i - 1], this.base2, this.mod2), charToInt(s[i]), this.mod2);
this.power2[i] = this.mul(this.power2[i - 1], this.base2, this.mod2);
}
}
RabinKarpHash.prototype.add = function(a, b, mod) {
a += b;
if (a >= mod) a -= mod;
return a;
};
RabinKarpHash.prototype.sub = function(a, b, mod) {
a -= b;
if (a < 0) a += mod;
return a;
};
RabinKarpHash.prototype.mul = function(a, b, mod) {
return ((a * b) % mod + mod) % mod;
};
RabinKarpHash.prototype.getSubHash = function(l, r) {
let h1 = this.hash1[r];
let h2 = this.hash2[r];
if (l > 0) {
h1 = this.sub(h1, this.mul(this.hash1[l - 1], this.power1[r - l + 1], this.mod1), this.mod1);
h2 = this.sub(h2, this.mul(this.hash2[l - 1], this.power2[r - l + 1], this.mod2), this.mod2);
}
return [h1, h2];
};
function palindromicSubstr(s) {
const n = s.length;
const mark = Array.from({ length: n }, () => Array(n).fill(false));
const disPalinSet = new Set();
const rk = new RabinKarpHash(s);
// check for odd length palindromes
for (let i = 0; i < n; i++) {
let left = i, right = i;
while (left >= 0 && right < n && s[left] === s[right]) {
const [h1, h2] = rk.getSubHash(left, right);
const key = `${h1}#${h2}`;
if (!disPalinSet.has(key)) {
disPalinSet.add(key);
mark[left][right] = true;
}
left--;
right++;
}
}
// check for even length palindromes
for (let i = 0; i < n - 1; i++) {
let left = i, right = i + 1;
while (left >= 0 && right < n && s[left] === s[right]) {
const [h1, h2] = rk.getSubHash(left, right);
const key = `${h1}#${h2}`;
if (!disPalinSet.has(key)) {
disPalinSet.add(key);
mark[left][right] = true;
}
left--;
right++;
}
}
const res = [];
for (let i = 0; i < n; i++) {
let sub = "";
for (let j = i; j < n; j++) {
sub += s[j];
if (mark[i][j]) {
res.push(sub);
}
}
}
return res;
}
// Driver Code
const s = "abaaa";
const result = palindromicSubstr(s);
console.log(result.join(" "));
Time Complexity: O(n² × log n), in the worst case, there can be O(n²) palindromic substrings, and each insertion into the set of hashes takes O(log n) time due to balanced BST structure, resulting in O(n² log n) total time.
Auxiliary Space: O(n²), we use a 2D mark array of size O(n²) and a set that may store up to O(n²) unique palindrome hashes, leading to overall O(n²) auxiliary space.
[Expected Approach] Using Dynamic Programming and KMP Algorithm - O(n^2) Time and O(n^2) Space
The idea is to identify all palindromic substrings in a given string using a dynamic programming method, then eliminate duplicates by leveraging the KMP algorithm, and finally print the distinct palindromes along with their count.
Follow the below given steps:
- First, for every possible substring, use dynamic programming to check if it is a palindrome.
- Next, for every index starting from 0, apply the KMP algorithm to compare prefixes and suffixes. If a substring is both a palindrome and its prefix matches its suffix, mark it (for example, by setting the corresponding dp value to false) so that duplicate occurrences are removed.
- Finally, iterate over all substrings and print those that remain marked as palindromic in the dp array; the number of such entries gives the total count of distinct palindromic substrings.
C++
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> palindromicSubstr(string &s) {
int n = s.length();
// Create a 2D array
vector<vector<bool>> dp(n, vector<bool>(n, false));
for (int i = 0; i < n; i++) {
// base case every char is palindrome
dp[i][i] = 1;
// check for every substring of length 2
if (i < n && s[i] == s[i + 1]) {
dp[i][i + 1] = 1;
}
}
// check every substring of length
// greater than 2 for palindrome
for (int len = 3; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
if (s[i] == s[i + (len - 1)]
&& dp[i + 1][i + (len - 1) - 1]) {
dp[i][i + (len - 1)] = true;
}
}
}
// create an array of size n
// to operate the kmp algorithm
vector<int> kmp(n, 0);
for (int i = 0; i < n; i++) {
// starting kmp for every i from 0 to n-1
int j = 0, k = 1;
while (k + i < n) {
if (s[j + i] == s[k + i]) {
// make suffix to be false,if this
// suffix is palindrome then
// it is included in prefix
dp[k + i - j][k + i] = false;
kmp[k++] = ++j;
}
else if (j > 0) {
j = kmp[j - 1];
}
else {
kmp[k++] = 0;
}
}
}
// Create an array to store the result
vector<string> result;
for (int i = 0; i < n; i++) {
// to store the current string
string cur;
for (int j = i; j < n; j++) {
cur += s[j];
if (dp[i][j]) {
result.push_back(cur);
}
}
}
return result;
}
int main() {
string s = "abaaa";
vector<string> result = palindromicSubstr(s);
for(string s : result)
cout << s << " ";
return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;
class GfG {
static ArrayList<String> palindromicSubstr(String s) {
int n = s.length();
// Create a 2D array
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) {
// base case every char is palindrome
dp[i][i] = true;
// check for every substring of length 2
if (i < n - 1 && s.charAt(i) == s.charAt(i + 1)) {
dp[i][i + 1] = true;
}
}
// check every substring of length
// greater than 2 for palindrome
for (int len = 3; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
if (s.charAt(i) == s.charAt(i + len - 1)
&& dp[i + 1][i + len - 2]) {
dp[i][i + len - 1] = true;
}
}
}
// create an array of size n
// to operate the kmp algorithm
int[] kmp = new int[n];
Arrays.fill(kmp, 0);
for (int i = 0; i < n; i++) {
// starting kmp for every i from 0 to n-1
int j = 0, k = 1;
while (k + i < n) {
if (s.charAt(j + i) == s.charAt(k + i)) {
// make suffix to be false, if this
// suffix is palindrome then
// it is included in prefix
dp[k + i - j][k + i] = false;
kmp[k++] = ++j;
}
else if (j > 0) {
j = kmp[j - 1];
}
else {
kmp[k++] = 0;
}
}
}
// Create an array to store the result
ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < n; i++) {
// to store the current string
String cur = "";
for (int j = i; j < n; j++) {
cur += s.charAt(j);
if (dp[i][j]) {
result.add(cur);
}
}
}
return result;
}
public static void main(String[] args) {
String s = "abaaa";
ArrayList<String> result = palindromicSubstr(s);
for (String s1 : result)
System.out.print(s1 + " ");
}
}
Python
def palindromicSubstr(s):
n = len(s)
# Create a 2D array
dp = [[False for _ in range(n)] for _ in range(n)]
for i in range(n):
# base case every char is palindrome
dp[i][i] = True
# check for every substring of length 2
if i < n - 1 and s[i] == s[i + 1]:
dp[i][i + 1] = True
# check every substring of length
# greater than 2 for palindrome
for length in range(3, n + 1):
for i in range(n - length + 1):
j = i + length - 1
if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
# create an array of size n
# to operate the kmp algorithm
kmp = [0] * n
for i in range(n):
# starting kmp for every i from 0 to n-1
j = 0
k = 1
while k + i < n:
if s[i + j] == s[i + k]:
# make suffix to be false, if this
# suffix is palindrome then
# it is included in prefix
dp[i + k - j][i + k] = False
kmp[k] = j + 1
j += 1
k += 1
elif j > 0:
j = kmp[j - 1]
else:
kmp[k] = 0
k += 1
# Create an array to store the result
result = []
for i in range(n):
# to store the current string
cur = ""
for j in range(i, n):
cur += s[j]
if dp[i][j]:
result.append(cur)
return result
if __name__ == "__main__":
s = "abaaa"
result = palindromicSubstr(s)
for s in result:
print(s, end=" ")
C#
using System;
using System.Collections.Generic;
class GfG {
static List<string> palindromicSubstr(ref string s) {
int n = s.Length;
// Create a 2D array
bool[,] dp = new bool[n, n];
for (int i = 0; i < n; i++) {
// base case every char is palindrome
dp[i, i] = true;
// check for every substring of length 2
if (i < n - 1 && s[i] == s[i + 1])
dp[i, i + 1] = true;
}
// check every substring of length
// greater than 2 for palindrome
for (int len = 3; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1;
if (s[i] == s[j] && dp[i + 1, j - 1])
dp[i, j] = true;
}
}
// create an array of size n
// to operate the kmp algorithm
int[] kmp = new int[n];
for (int i = 0; i < n; i++) {
kmp[i] = 0;
}
for (int i = 0; i < n; i++) {
// starting kmp for every i from 0 to n-1
int j = 0, k = 1;
while (k + i < n) {
if (s[i + j] == s[i + k]) {
// make suffix to be false, if this
// suffix is palindrome then
// it is included in prefix
dp[i + k - j, i + k] = false;
kmp[k] = ++j;
k++;
}
else if (j > 0) {
j = kmp[j - 1];
}
else {
kmp[k] = 0;
k++;
}
}
}
// Create an array to store the result
List<string> result = new List<string>();
for (int i = 0; i < n; i++) {
// to store the current string
string cur = "";
for (int j = i; j < n; j++) {
cur += s[j];
if (dp[i, j])
result.Add(cur);
}
}
return result;
}
static void Main() {
string s = "abaaa";
List<string> result = palindromicSubstr(ref s);
foreach (string ss in result)
Console.Write(ss + " ");
}
}
JavaScript
function palindromicSubstr(s) {
let n = s.length;
// Create a 2D array
let dp = new Array(n);
for (let i = 0; i < n; i++) {
dp[i] = new Array(n).fill(false);
}
for (let i = 0; i < n; i++) {
// base case every char is palindrome
dp[i][i] = true;
// check for every substring of length 2
if (i < n - 1 && s[i] === s[i + 1])
dp[i][i + 1] = true;
}
// check every substring of length
// greater than 2 for palindrome
for (let len = 3; len <= n; len++) {
for (let i = 0; i + len - 1 < n; i++) {
let j = i + len - 1;
if (s[i] === s[j] && dp[i + 1][j - 1])
dp[i][j] = true;
}
}
// create an array of size n
// to operate the kmp algorithm
let kmp = new Array(n).fill(0);
for (let i = 0; i < n; i++) {
// starting kmp for every i from 0 to n-1
let j = 0, k = 1;
while (k + i < n) {
if (s[i + j] === s[i + k]) {
// make suffix to be false, if this
// suffix is palindrome then
// it is included in prefix
dp[i + k - j][i + k] = false;
kmp[k] = ++j;
k++;
} else if (j > 0) {
j = kmp[j - 1];
} else {
kmp[k] = 0;
k++;
}
}
}
// Create an array to store the result
let result = [];
for (let i = 0; i < n; i++) {
// to store the current string
let cur = "";
for (let j = i; j < n; j++) {
cur += s[j];
if (dp[i][j])
result.push(cur);
}
}
return result;
}
// Driver Code
let s = "abaaa";
let result = palindromicSubstr(s);
console.log(result.join(" "));
Related Article:
Count All Palindrome Sub-Strings in a String
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem