Palindrome pair in an array of words (or strings)

Given a list of words, find if any of the two words can be joined to form a palindrome.

Examples:

```Input  : list[] = {"geekf", "geeks", "or",
"keeg", "abc", "bc"}
Output : Yes
There is a pair "geekf" and "keeg"

Input : list[] =  {"abc", "xyxcba", "geekst", "or",
"keeg", "bc"}
Output : Yes
There is a pair "abc" and "xyxcba"
```

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

Simple approach:

```1- Consider each pair one by one.
2- Check if any of the pairs forms a palindrome
after concatenating them.
3- Return true, if any such pair exists.
4- Else, return false.
```

C++

 `// C++ program to find if there is a pair that ` `// can form a palindrome. ` `#include ` `using` `namespace` `std; ` ` `  `// Utility function to check if a string is a ` `// palindrome ` `bool` `isPalindrome(string str) ` `{ ` `    ``int` `len = str.length(); ` ` `  `    ``// compare each character from starting ` `    ``// with its corresponding character from last ` `    ``for` `(``int` `i = 0; i < len/2; i++ ) ` `        ``if` `(str[i] != str[len-i-1]) ` `            ``return` `false``; ` ` `  `    ``return` `true``; ` `} ` ` `  `// Function to check if a palindrome pair exists ` `bool` `checkPalindromePair(vector vect) ` `{ ` `    ``// Consider each pair one by one ` `    ``for` `(``int` `i = 0; i< vect.size()-1; i++) ` `    ``{ ` `        ``for` `(``int` `j = i+1; j< vect.size() ; j++) ` `        ``{ ` `            ``string check_str = ``""``; ` ` `  `            ``// concatenate both strings ` `            ``check_str = check_str + vect[i] + vect[j]; ` ` `  `            ``// check if the concatenated string is ` `            ``// palindrome ` `            ``if` `(isPalindrome(check_str)) ` `                ``return` `true``; ` `        ``} ` `    ``} ` `    ``return` `false``; ` `} ` ` `  `// Driver code ` `int` `main() ` `{ ` `    ``vector vect = {``"geekf"``, ``"geeks"``, ``"or"``, ` `                            ``"keeg"``, ``"abc"``, ``"bc"``}; ` ` `  ` `  `    ``checkPalindromePair(vect)? cout << ``"Yes"` `: ` `                               ``cout << ``"No"``; ` `    ``return` `0; ` `} `

Java

 `// Java program to find if there is a pair that ` `// can form a palindrome. ` `import` `java.util.Arrays; ` `import` `java.util.List; ` `public` `class` `Palin_pair1 { ` `         `  `    ``// Utility function to check if a string is a ` `    ``// palindrome ` `    ``static` `boolean` `isPalindrome(String str) ` `    ``{ ` `        ``int` `len = str.length(); ` `      `  `        ``// compare each character from starting ` `        ``// with its corresponding character from last ` `        ``for` `(``int` `i = ``0``; i < len/``2``; i++ ) ` `            ``if` `(str.charAt(i) != str.charAt(len-i-``1``)) ` `                ``return` `false``; ` `      `  `        ``return` `true``; ` `    ``} ` `      `  `    ``// Function to check if a palindrome pair exists ` `    ``static` `boolean` `checkPalindromePair(List vect) ` `    ``{ ` `        ``// Consider each pair one by one ` `        ``for` `(``int` `i = ``0``; i< vect.size()-``1``; i++) ` `        ``{ ` `            ``for` `(``int` `j = i+``1``; j< vect.size() ; j++) ` `            ``{ ` `                ``String check_str = ``""``; ` `      `  `                ``// concatenate both strings ` `                ``check_str = check_str + vect.get(i) + vect.get(j); ` `      `  `                ``// check if the concatenated string is ` `                ``// palindrome ` `                ``if` `(isPalindrome(check_str)) ` `                    ``return` `true``; ` `            ``} ` `        ``} ` `        ``return` `false``; ` `    ``} ` `      `  `    ``// Driver code ` `    ``public` `static` `void` `main(String args[]) ` `    ``{ ` `        ``List vect = Arrays.asList(``"geekf"``, ``"geeks"``, ``"or"``, ` `                                ``"keeg"``, ``"abc"``, ``"bc"``); ` `      `  `      `  `        ``if` `(checkPalindromePair(vect) == ``true``) ` `            ``System.out.println(``"Yes"``); ` `        ``else`     `            ``System.out.println(``"No"``); ` `    ``} ` `} ` `//This code is contributed by Sumit Ghosh `

Output:

``` Yes
```

Time Complexity : O(n2k)
Here n is the number of the words in the list and k is the maximum length that is checked for a palindrome.

Efficient method
It can be done in an efficient manner by using the Trie data structure. The idea is to maintain a Trie of the reverse of all words.

```1) Create an empty Trie.
2) Do following for every word:-
a) Insert reverse of current word.
b) Also store up to which index it is
a palindrome.
3) Traverse list of words again and do following
for every word.
a) If it is available in Trie then return true
b) If it is partially available
Check the remaining word is palindrome or not
If yes then return true that means a pair
forms a palindrome.
Note: Position upto which the word is palindrome
is stored because of these type of cases.
```

C++

 `// C++ program to check if there is a pair that ` `// of above method using Trie ` `#include ` `using` `namespace` `std; ` `#define ARRAY_SIZE(a) sizeof(a)/sizeof(a) ` ` `  `// Alphabet size (# of symbols) ` `#define ALPHABET_SIZE (26) ` ` `  `// Converts key current character into index ` `// use only 'a' through 'z' and lower case ` `#define CHAR_TO_INDEX(c) ((int)c - (int)'a') ` ` `  `// Trie node ` `struct` `TrieNode ` `{ ` `    ``struct` `TrieNode *children[ALPHABET_SIZE]; ` `    ``vector<``int``> pos; ``// To store palindromic ` `                     ``// positions in str ` `    ``int` `id; ` ` `  `    ``// isLeaf is true if the node represents ` `    ``// end of a word ` `    ``bool` `isLeaf; ` `}; ` ` `  `// Returns new Trie node (initialized to NULLs) ` `struct` `TrieNode *getNode(``void``) ` `{ ` `    ``struct` `TrieNode *pNode = ``new` `TrieNode; ` `    ``pNode->isLeaf = ``false``; ` `    ``for` `(``int` `i = 0; i < ALPHABET_SIZE; i++) ` `            ``pNode->children[i] = NULL; ` ` `  `    ``return` `pNode; ` `} ` ` `  `// Utility function to check if a string is a ` `// palindrome ` `bool` `isPalindrome(string str, ``int` `i, ``int` `len) ` `{ ` `    ``// compare each character from starting ` `    ``// with its corresponding character from last ` `    ``while` `(i < len) ` `    ``{ ` `        ``if` `(str[i] != str[len]) ` `            ``return` `false``; ` `        ``i++, len--; ` `    ``} ` ` `  `    ``return` `true``; ` `} ` ` `  `// If not present, inserts reverse of key into Trie. If  ` `// the key is prefix of a Trie node, just mark leaf node ` `void` `insert(``struct` `TrieNode* root, string key, ``int` `id) ` `{ ` `    ``struct` `TrieNode *pCrawl = root; ` ` `  `    ``// Start traversing word from the last ` `    ``for` `(``int` `level = key.length()-1; level >=0; level--) ` `    ``{ ` `        ``// If it is not available in Trie, then ` `        ``// store it ` `        ``int` `index = CHAR_TO_INDEX(key[level]); ` `        ``if` `(!pCrawl->children[index]) ` `            ``pCrawl->children[index] = getNode(); ` ` `  `        ``// If current word is palindrome till this ` `        ``// level, store index of current word. ` `        ``if` `(isPalindrome(key, 0, level)) ` `            ``(pCrawl->pos).push_back(id); ` ` `  `        ``pCrawl = pCrawl->children[index]; ` `    ``} ` `    ``pCrawl->id = id; ` `    ``pCrawl->pos.push_back(id); ` ` `  `    ``// mark last node as leaf ` `    ``pCrawl->isLeaf = ``true``; ` `} ` ` `  `// Returns true if key presents in Trie, else false ` `void` `search(``struct` `TrieNode *root, string key, ` `            ``int` `id, vector > &result) ` `{ ` `    ``struct` `TrieNode *pCrawl = root; ` `    ``for` `(``int` `level = 0; level < key.length(); level++) ` `    ``{ ` `        ``int` `index = CHAR_TO_INDEX(key[level]); ` ` `  `        ``// If it is present also check upto which index ` `        ``// it is palindrome ` `        ``if` `(pCrawl->id >= 0 && pCrawl->id != id && ` `            ``isPalindrome(key, level, key.size()-1)) ` `            ``result.push_back({id, pCrawl->id}); ` ` `  `        ``// If not present then return ` `        ``if` `(!pCrawl->children[index]) ` `            ``return``; ` ` `  `        ``pCrawl = pCrawl->children[index]; ` `    ``} ` ` `  `    ``for` `(``int` `i: pCrawl->pos) ` `    ``{ ` `        ``if` `(i == id) ` `            ``continue``; ` `        ``result.push_back({id, i}); ` `    ``} ` `} ` ` `  `// Function to check if a palindrome pair exists ` `bool` `checkPalindromePair(vector vect) ` `{ ` `    ``// Construct trie ` `    ``struct` `TrieNode *root = getNode(); ` `    ``for` `(``int` `i = 0; i < vect.size(); i++) ` `        ``insert(root, vect[i], i); ` ` `  `    ``// Search for different keys ` `    ``vector > result; ` `    ``for` `(``int` `i=0; i 0) ` `           ``return` `true``; ` `    ``} ` ` `  `    ``return` `false``; ` `} ` ` `  `// Driver code ` `int` `main() ` `{ ` `    ``vector vect = {``"geekf"``, ``"geeks"``, ``"or"``, ` `                            ``"keeg"``, ``"abc"``, ``"bc"``}; ` ` `  ` `  `    ``checkPalindromePair(vect)? cout << ``"Yes"` `: ` `                               ``cout << ``"No"``; ` `    ``return` `0; ` `} `

Java

 `//Java program to check if there is a pair that ` `//of above method using Trie ` `import` `java.util.ArrayList; ` `import` `java.util.Arrays; ` `import` `java.util.List; ` ` `  `public` `class` `Palin_pair2 { ` ` `  `    ``// Alphabet size (# of symbols) ` `    ``static` `final` `int` `ALPHABET_SIZE = ``26``; ` ` `  `    ``// Trie node ` `    ``static` `class` `TrieNode { ` `        ``TrieNode[] children = ``new` `TrieNode[ALPHABET_SIZE]; ` `        ``List pos; ``// To store palindromic ` `                            ``// positions in str ` `        ``int` `id; ` ` `  `        ``// isLeaf is true if the node represents ` `        ``// end of a word ` `        ``boolean` `isLeaf; ` ` `  `        ``// constructor ` `        ``public` `TrieNode() { ` `            ``isLeaf = ``false``; ` `            ``pos = ``new` `ArrayList<>(); ` `            ``for` `(``int` `i = ``0``; i < ALPHABET_SIZE; i++) ` `                ``children[i] = ``null``; ` `        ``} ` `    ``} ` ` `  `    ``// Utility function to check if a string is a ` `    ``// palindrome ` `    ``static` `boolean` `isPalindrome(String str, ``int` `i, ``int` `len) { ` `        ``// compare each character from starting ` `        ``// with its corresponding character from last ` `        ``while` `(i < len) { ` `            ``if` `(str.charAt(i) != str.charAt(len)) ` `                ``return` `false``; ` ` `  `            ``i++; ` `            ``len--; ` `        ``} ` `        ``return` `true``; ` `    ``} ` ` `  `    ``// If not present, inserts reverse of key into Trie. If ` `    ``// the key is prefix of a Trie node, just mark leaf node ` `    ``static` `void` `insert(TrieNode root, String key, ``int` `id) { ` `        ``TrieNode pCrawl = root; ` ` `  `        ``// Start traversing word from the last ` `        ``for` `(``int` `level = key.length() - ``1``; level >= ``0``; level--) { ` `            ``// If it is not available in Trie, then ` `            ``// store it ` `            ``int` `index = key.charAt(level) - ``'a'``; ` `            ``if` `(pCrawl.children[index] == ``null``) ` `                ``pCrawl.children[index] = ``new` `TrieNode(); ` ` `  `            ``// If current word is palindrome till this ` `            ``// level, store index of current word. ` `            ``if` `(isPalindrome(key, ``0``, level)) ` `                ``(pCrawl.pos).add(id); ` ` `  `            ``pCrawl = pCrawl.children[index]; ` `        ``} ` `        ``pCrawl.id = id; ` `        ``pCrawl.pos.add(id); ` ` `  `        ``// mark last node as leaf ` `        ``pCrawl.isLeaf = ``true``; ` `    ``} ` ` `  `    ``// list to store result  ` `    ``static` `List> result; ` ` `  `    ``// Returns true if key presents in Trie, else false ` `    ``static` `void` `search(TrieNode root, String key, ``int` `id) { ` `        ``TrieNode pCrawl = root; ` `        ``for` `(``int` `level = ``0``; level < key.length(); level++) { ` `            ``int` `index = key.charAt(level) - ``'a'``; ` ` `  `            ``// If it is present also check upto which index ` `            ``// it is palindrome ` `            ``if` `(pCrawl.id >= ``0` `&& pCrawl.id != id ` `                    ``&& isPalindrome(key, level, key.length() - ``1``)) { ` `                ``List l = ``new` `ArrayList<>(); ` `                ``l.add(id); ` `                ``l.add(pCrawl.id); ` `                ``result.add(l); ` `            ``} ` ` `  `            ``// If not present then return ` `            ``if` `(pCrawl.children[index] == ``null``) ` `                ``return``; ` ` `  `            ``pCrawl = pCrawl.children[index]; ` `        ``} ` ` `  `        ``for` `(``int` `i : pCrawl.pos) { ` `            ``if` `(i == id) ` `                ``continue``; ` `            ``List l = ``new` `ArrayList<>(); ` `            ``l.add(id); ` `            ``l.add(i); ` `            ``result.add(l); ` `        ``} ` `    ``} ` ` `  `    ``// Function to check if a palindrome pair exists ` `    ``static` `boolean` `checkPalindromePair(List vect) { ` `         `  `        ``// Construct trie ` `        ``TrieNode root = ``new` `TrieNode(); ` `        ``for` `(``int` `i = ``0``; i < vect.size(); i++) ` `            ``insert(root, vect.get(i), i); ` ` `  `        ``// Search for different keys ` `        ``result = ``new` `ArrayList<>(); ` `        ``for` `(``int` `i = ``0``; i < vect.size(); i++) { ` `            ``search(root, vect.get(i), i); ` ` `  `            ``if` `(result.size() > ``0``) ` `                ``return` `true``; ` `        ``} ` ` `  `        ``return` `false``; ` `    ``} ` ` `  `    ``// Driver code ` `    ``public` `static` `void` `main(String args[]) { ` `        ``List vect = Arrays.asList(``"geekf"``, ``"geeks"``,  ` `                            ``"or"``, ``"keeg"``, ``"abc"``, ``"bc"``); ` ` `  `        ``if` `(checkPalindromePair(vect) == ``true``) ` `            ``System.out.println(``"Yes"``); ` `        ``else` `            ``System.out.println(``"No"``); ` `    ``} ` `} ` `//This code is contributed by Sumit Ghosh `

Output:

```Yes
```

Time Complexity: O(nk2)
Where n is the number of words in the list and k is the maximum length that is checked for palindrome.

This article is contributed by Sahil Chhabra (akku). 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.