# 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: 4
Explanation:
Possible Splits: {“a”, “aaaa”}, {“aa”, “aaa”}, {“aaa”, “aa”}, {“aaaa”, “a”}

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

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

Naive Approach: The naive approach is to split the string at each possible index and check if both the subtrings 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++

 `// 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

 `// 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 `

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++

 `// 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<``int``> prefixHash(MAXN); ` ` `  `// Stores suffix hash ` `vector<``int``> suffixHash(MAXN); ` ` `  `// Stores inverse modulo ` `// of P for prefix ` `vector<``int``> inversePrefix(MAXN); ` ` `  `// Stores inverse modulo ` `// of P  for suffix ` `vector<``int``> 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 < n; i++) { ` ` `  `        ``// Calculate Prefix Hash ` `        ``prefixHash[i] = (1LL ` `                         ``* ``int``(s[i] ` `                               ``- ``'a'` `+ 1) ` `                         ``* x) ` `                        ``% MOD; ` ` `  `        ``if` `(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 < n - 1) ` `            ``suffixHash[i] ` `                ``= (suffixHash[i] ` `                   ``+ suffixHash[i + 1]) ` `                  ``% MOD; ` ` `  `        ``// computingCompute inverse modulo ` `        ``// of P ^ i for division ` `        ``// using Fermat Little theorem ` `        ``inverseSuffix[i] = power(x, MOD - 2, ` `                                 ``MOD); ` ` `  `        ``x = (1LL * x * P) % MOD; ` `    ``} ` `} ` ` `  `// Function to return Prefix ` `// Hash of substring ` `int` `getPrefixHash(``int` `l, ``int` `r) ` `{ ` `    ``// Calculate Prefix Hash ` `    ``// from l to r ` `    ``int` `h = prefixHash[r] ` `            ``- (l > 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...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.

My Personal Notes arrow_drop_up Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

Improved By : SoumikMondal