# Count of ways to split given string into two non-empty palindromes

Given a string S, the task is to find the number of ways to split the given string S into two non-empty palindromic strings.
Examples:

Input: S = “aaaaa”
Output:
Explanation:
Possible Splits: {“a”, “aaaa”}, {“aa”, “aaa”}, {“aaa”, “aa”}, {“aaaa”, “a”}

Input: S = “abacc”
Output:
Explanation:
Only possible split is “aba”, “cc”.

Naive Approach: The naive approach is to split the string at each possible index and check if both the substrings are palindromic or not. If yes then increment the count for that index. Print the final count.

Below is the implementation of the above approach:

 `// C++ Program to implement ` `// the above approach ` `#include ` `using` `namespace` `std; ` ` `  `// Function to check whether the ` `// substring from l to r is ` `// palindrome or not ` `bool` `isPalindrome(``int` `l, ``int` `r, ` `                  ``string& s) ` `{ ` ` `  `    ``while` `(l <= r) { ` ` `  `        ``// If characters at l and ` `        ``// r differ ` `        ``if` `(s[l] != s[r]) ` ` `  `            ``// Not a palindrome ` `            ``return` `false``; ` ` `  `        ``l++; ` `        ``r--; ` `    ``} ` ` `  `    ``// If the string is ` `    ``// a palindrome ` `    ``return` `true``; ` `} ` ` `  `// Function to count and return ` `// the number of possible splits ` `int` `numWays(string& s) ` `{ ` `    ``int` `n = s.length(); ` ` `  `    ``// Stores the count ` `    ``// of splits ` `    ``int` `ans = 0; ` `    ``for` `(``int` `i = 0; ` `         ``i < n - 1; i++) { ` ` `  `        ``// Check if the two substrings ` `        ``// after the split are ` `        ``// palindromic or not ` `        ``if` `(isPalindrome(0, i, s) ` `            ``&& isPalindrome(i + 1, ` `                            ``n - 1, s)) { ` ` `  `            ``// If both are palindromes ` `            ``ans++; ` `        ``} ` `    ``} ` ` `  `    ``// Print the final count ` `    ``return` `ans; ` `} ` ` `  `// Driver Code ` `int` `main() ` `{ ` `    ``string S = ``"aaaaa"``; ` ` `  `    ``cout << numWays(S); ` `    ``return` `0; ` `} `

 `// Java program to implement ` `// the above approach ` `class` `GFG{ ` `     `  `// Function to check whether the ` `// substring from l to r is ` `// palindrome or not ` `public` `static` `boolean` `isPalindrome(``int` `l, ``int` `r, ` `                                   ``String s) ` `{ ` `    ``while` `(l <= r) ` `    ``{ ` `         `  `        ``// If characters at l and ` `        ``// r differ ` `        ``if` `(s.charAt(l) != s.charAt(r)) ` `             `  `            ``// Not a palindrome ` `            ``return` `false``; ` `             `  `        ``l++; ` `        ``r--; ` `    ``} ` ` `  `    ``// If the string is ` `    ``// a palindrome ` `    ``return` `true``; ` `} ` ` `  `// Function to count and return ` `// the number of possible splits ` `public` `static` `int` `numWays(String s) ` `{ ` `    ``int` `n = s.length(); ` ` `  `    ``// Stores the count ` `    ``// of splits ` `    ``int` `ans = ``0``; ` `    ``for``(``int` `i = ``0``; i < n - ``1``; i++) ` `    ``{ ` `        `  `       ``// Check if the two substrings ` `       ``// after the split are ` `       ``// palindromic or not ` `       ``if` `(isPalindrome(``0``, i, s) &&  ` `           ``isPalindrome(i + ``1``, n - ``1``, s)) ` `       ``{ ` `            `  `           ``// If both are palindromes ` `           ``ans++; ` `       ``} ` `    ``} ` `     `  `    ``// Print the final count ` `    ``return` `ans; ` `} ` ` `  `// Driver Code ` `public` `static` `void` `main(String args[]) ` `{ ` `    ``String S = ``"aaaaa"``; ` ` `  `    ``System.out.println(numWays(S)); ` `} ` `} ` ` `  `// This code is contributed by SoumikMondal `

 `# Python3 program to implement ` `# the above approach ` ` `  `# Function to check whether the ` `# substring from l to r is ` `# palindrome or not ` `def` `isPalindrome(l, r, s): ` ` `  `    ``while` `(l <``=` `r): ` `         `  `        ``# If characters at l and ` `        ``# r differ ` `        ``if` `(s[l] !``=` `s[r]): ` `             `  `            ``# Not a palindrome ` `            ``return` `bool``(``False``) ` `             `  `        ``l ``+``=` `1` `        ``r ``-``=` `1` ` `  `    ``# If the string is ` `    ``# a palindrome ` `    ``return` `bool``(``True``) ` ` `  `# Function to count and return ` `# the number of possible splits ` `def` `numWays(s): ` `     `  `    ``n ``=` `len``(s) ` ` `  `    ``# Stores the count ` `    ``# of splits ` `    ``ans ``=` `0` `    ``for` `i ``in` `range``(n ``-` `1``): ` `         `  `        ``# Check if the two substrings ` `        ``# after the split are ` `        ``# palindromic or not ` `        ``if` `(isPalindrome(``0``, i, s) ``and`  `            ``isPalindrome(i ``+` `1``, n ``-` `1``, s)): ` `                 `  `            ``# If both are palindromes ` `            ``ans ``+``=` `1` `     `  `    ``# Print the final count ` `    ``return` `ans ` ` `  `# Driver Code ` `S ``=` `"aaaaa"` ` `  `print``(numWays(S)) ` ` `  `# This code is contributed by divyeshrabadiya07 `

 `// C# program to implement ` `// the above approach ` `using` `System; ` `class` `GFG{ ` `      `  `// Function to check whether the ` `// substring from l to r is ` `// palindrome or not ` `public` `static` `bool` `isPalindrome(``int` `l, ``int` `r, ` `                                ``string` `s) ` `{ ` `    ``while` `(l <= r) ` `    ``{ ` `          `  `        ``// If characters at l and ` `        ``// r differ ` `        ``if` `(s[l] != s[r]) ` `              `  `            ``// Not a palindrome ` `            ``return` `false``; ` `              `  `        ``l++; ` `        ``r--; ` `    ``} ` `  `  `    ``// If the string is ` `    ``// a palindrome ` `    ``return` `true``; ` `} ` `  `  `// Function to count and return ` `// the number of possible splits ` `public` `static` `int` `numWays(``string` `s) ` `{ ` `    ``int` `n = s.Length; ` `  `  `    ``// Stores the count ` `    ``// of splits ` `    ``int` `ans = 0; ` `    ``for``(``int` `i = 0; i < n - 1; i++) ` `    ``{ ` `         `  `       ``// Check if the two substrings ` `       ``// after the split are ` `       ``// palindromic or not ` `       ``if` `(isPalindrome(0, i, s) &&  ` `           ``isPalindrome(i + 1, n - 1, s)) ` `       ``{ ` `             `  `           ``// If both are palindromes ` `           ``ans++; ` `       ``} ` `    ``} ` `      `  `    ``// Print the final count ` `    ``return` `ans; ` `} ` `  `  `// Driver Code ` `public` `static` `void` `Main(``string` `[]args) ` `{ ` `    ``string` `S = ``"aaaaa"``; ` `  `  `    ``Console.Write(numWays(S)); ` `} ` `} ` ` `  `// This code is contributed by Rutvik`

Output:
```4
```

Time Complexity: O(N2)

Efficient Approach: The above approach can be optimized using the Hashing and Rabin-Karp Algorithm to store Prefix and Suffix Hashes of the string. Follow the steps below to solve the problem:

• Compute prefix and suffix hash of the given string.
• For every index i in the range [1, N – 1], check if the two substrings [0, i – 1] and [i, N – 1] are palindrome or not.
• To check if a substring [l, r] is a palindrome or not, simply check:
```PrefixHash[l - r] = SuffixHash[l - r]

```
• For every index i for which two substrings are found to be palindromic, increase the count.
• Print the final value of count.

Below is the implementation of the above approach:

 `// C++ Program to implement ` `// the above approach ` ` `  `#include  ` `using` `namespace` `std; ` ` `  `// Modulo for rolling hash ` `const` `int` `MOD = 1e9 + 9; ` ` `  `// Small prime for rolling hash ` `const` `int` `P = 37; ` ` `  `// Maximum length of string ` `const` `int` `MAXN = 1e5 + 5; ` ` `  `// Stores prefix hash ` `vector prefixHash(MAXN); ` ` `  `// Stores suffix hash ` `vector suffixHash(MAXN); ` ` `  `// Stores inverse modulo ` `// of P for prefix ` `vector inversePrefix(MAXN); ` ` `  `// Stores inverse modulo ` `// of P for suffix ` `vector inverseSuffix(MAXN); ` ` `  `int` `n; ` `int` `power(``int` `x, ``int` `y, ``int` `mod) ` `{ ` `    ``// Function to compute ` `    ``// power under modulo ` `    ``if` `(x == 0) ` `        ``return` `0; ` ` `  `    ``int` `ans = 1; ` `    ``while` `(y > 0) { ` `        ``if` `(y & 1) ` `            ``ans = (1LL * ans * x) ` `                ``% MOD; ` ` `  `        ``x = (1LL * x * x) % MOD; ` `        ``y >>= 1; ` `    ``} ` `    ``return` `ans; ` `} ` ` `  `// Precompte hashes for the ` `// given string ` `void` `preCompute(string& s) ` `{ ` ` `  `    ``int` `x = 1; ` `    ``for` `(``int` `i = 0; i 0) ` `            ``prefixHash[i] ` `                ``= (prefixHash[i] ` `                ``+ prefixHash[i - 1]) ` `                ``% MOD; ` ` `  `        ``// Compute inverse modulo ` `        ``// of P ^ i for division ` `        ``// using Fermat Little theorem ` `        ``inversePrefix[i] = power(x, MOD - 2, ` `                                ``MOD); ` ` `  `        ``x = (1LL * x * P) % MOD; ` `    ``} ` ` `  `    ``x = 1; ` ` `  `    ``// Calculate suffix hash ` `    ``for` `(``int` `i = n - 1; i >= 0; i--) { ` ` `  `        ``// Calculate and store hash ` `        ``suffixHash[i] ` `            ``= (1LL * ``int``(s[i] ` `                        ``- ``'a'` `+ 1) ` `            ``* x) ` `            ``% MOD; ` ` `  `        ``if` `(i 0 ` `                ``? prefixHash[l - 1] ` `                ``: 0); ` `    ``h = (h + MOD) % MOD; ` `    ``h = (1LL * h * inversePrefix[l]) ` `        ``% MOD; ` ` `  `    ``return` `h; ` `} ` ` `  `// Function to return Suffix ` `// Hash of substring ` `int` `getSuffixHash(``int` `l, ``int` `r) ` `{ ` `    ``// Calculate suffix hash ` `    ``// from l to r ` `    ``int` `h = suffixHash[l] ` `            ``- (r < n - 1 ` `                ``? suffixHash[r + 1] ` `                ``: 0); ` ` `  `    ``h = (h + MOD) % MOD; ` `    ``h = (1LL * h * inverseSuffix[r]) ` `        ``% MOD; ` ` `  `    ``return` `h; ` `} ` ` `  `int` `numWays(string& s) ` `{ ` `    ``n = s.length(); ` ` `  `    ``// Compute prefix and ` `    ``// suffix hashes ` `    ``preCompute(s); ` ` `  `    ``// Stores the number of ` `    ``// possible splits ` `    ``int` `ans = 0; ` `    ``for` `(``int` `i = 0; ` `        ``i < n - 1; i++) { ` ` `  `        ``int` `preHash = getPrefixHash(0, i); ` `        ``int` `sufHash = getSuffixHash(0, i); ` ` `  `        ``// If the substring s[0]...s[i] ` `        ``// is not palindromic ` `        ``if` `(preHash != sufHash) ` `            ``continue``; ` ` `  `        ``preHash = getPrefixHash(i + 1, ` `                                ``n - 1); ` `        ``sufHash = getSuffixHash(i + 1, ` `                                ``n - 1); ` ` `  `        ``// If the substring (i + 1, n - 1) ` `        ``// is not palindromic ` `        ``if` `(preHash != sufHash) ` `            ``continue``; ` ` `  `        ``// If both are palindromic ` `        ``ans++; ` `    ``} ` ` `  `    ``return` `ans; ` `} ` ` `  `// Driver Code ` `int` `main() ` `{ ` `    ``string s = ``"aaaaa"``; ` ` `  `    ``int` `ans = numWays(s); ` ` `  `    ``cout << ans << endl; ` ` `  `    ``return` `0; ` `} `

Output:
```4
```

Time Complexity: O(N * log(109))
Space Complexity: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.