# Queries to check if the path between two nodes in a tree is a palindrome

Given a tree with N nodes and N – 1 edges. Each edge of the tree is labeled by a string of lowercase english alphabets. You are given Q queries. In each query you are given two node x and y. For the path between x to y, the task is to check if it is possible to make a new palindrome string which use all the characters in the path from node x to node y. Note that you can use the characters in any order you like and root node is always 1.

Examples:

```Input:
1
(bbc)/   \(ac)
2     3
Q[][] = {{1, 2}, {2, 3}, {3, 1}, {3, 3}}
Output:
Yes
Yes
No
Yes
Query 1: "bbc" can be arranged into "bcb"
which is a palindrome.
Query 2: "bbcac" -> "bcacb"
Query 3: No permutation of "ac" is palindrome.
Query 4: "acac" -> "acca"

Input:
1
/    |     \
/(ab)  |(bca)  \(bc)
2        3         4
\(ab)
5
Q[][] = {{1, 5}, {4, 5}, {5, 4}}
Output:
Yes
No
No
```

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

Approach: For each query, the character count for path x to y has to be calculated. After finding the characters count, it can be easily checked whether the characters will form a palindrome or not using the approach discussed in this article.
Steps to get the character count for path x to y.

1. Set the initial character count for each node.
2. Update character count of the root’s child node and then repeat the same process for its child node.
3. Find LCA (Lowest Common Ancestor) of x and y.
4. Calculate character count for path x to y with the following step:
For each character charCount[i] = (xNodeCharCount[i] – lcaNodeCharCount[i]) + (yNodeCharCount[i] – lcaNodeCharCount[i])
5. Now check whether a palindrome can be formed with the current count of characters.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the approach ` `#include ` `using` `namespace` `std; ` ` `  `const` `int` `MAX_SIZE = 100005, MAX_CHAR = 26; ` `int` `nodeCharactersCount[MAX_SIZE][MAX_CHAR]; ` ` `  `vector<``int``> tree[MAX_SIZE]; ` ` `  `// Function that returns true if a palindromic ` `// string can be formed using the given characters ` `bool` `canFormPalindrome(``int``* charArray) ` `{ ` ` `  `    ``// Count odd occurring characters ` `    ``int` `oddCount = 0; ` `    ``for` `(``int` `i = 0; i < MAX_CHAR; i++) { ` `        ``if` `(charArray[i] % 2 == 1) ` `            ``oddCount++; ` `    ``} ` `    ``// Return false if odd count is more than 1, ` `    ``if` `(oddCount >= 2) ` `        ``return` `false``; ` `    ``else` `        ``return` `true``; ` `} ` ` `  `// Find to find the Lowest Common ` `// Ancestor in the tree ` `int` `LCA(``int` `currentNode, ``int` `x, ``int` `y) ` `{ ` `    ``// Base case ` `    ``if` `(currentNode == x) ` `        ``return` `x; ` ` `  `    ``// Base case ` `    ``if` `(currentNode == y) ` `        ``return` `y; ` `    ``int` `xLca, yLca; ` ` `  `    ``// Initially value -1 denotes that ` `    ``// we need to find the ancestor ` `    ``xLca = yLca = -1; ` ` `  `    ``// -1 denotes that we need to find the lca ` `    ``// for x and y, values other than x and y ` `    ``// will be the LCA of x and y ` `    ``int` `gotLca = -1; ` ` `  `    ``// Iterating in the child ` `    ``// substree of the currentNode ` `    ``for` `(``int` `l = 0; l < tree[currentNode].size(); l++) { ` ` `  `        ``// Next node that will be checked ` `        ``int` `nextNode = tree[currentNode][l]; ` ` `  `        ``// Look for the next child subtree ` `        ``int` `out_ = LCA(nextNode, x, y); ` ` `  `        ``if` `(out_ == x) ` `            ``xLca = out_; ` `        ``if` `(out_ == y) ` `            ``yLca = out_; ` ` `  `        ``// Both the nodes exist in the different ` `        ``// subtrees, in this case parent node ` `        ``// will be the lca ` `        ``if` `(xLca != -1 and yLca != -1) ` `            ``return` `currentNode; ` ` `  `        ``// Handle the cases where LCA is already ` `        ``// calculated or both x and y are present ` `        ``// in the same subtree ` `        ``if` `(out_ != -1) ` `            ``gotLca = out_; ` `    ``} ` `    ``return` `gotLca; ` `} ` ` `  `// Function to calculate the character count for ` `// each path from node i to 1 (root node) ` `void` `buildTree(``int` `i) ` `{ ` `    ``for` `(``int` `l = 0; l < tree[i].size(); l++) { ` ` `  `        ``int` `nextNode = tree[i][l]; ` `        ``for` `(``int` `j = 0; j < MAX_CHAR; j++) { ` ` `  `            ``// Updating the character count ` `            ``// for each node ` `            ``nodeCharactersCount[nextNode][j] ` `                ``+= nodeCharactersCount[i][j]; ` `        ``} ` ` `  `        ``// Look for the child subtree ` `        ``buildTree(nextNode); ` `    ``} ` `} ` ` `  `// Function that returns true if a palindromic path ` `// is possible between the nodes x and y ` `bool` `canFormPalindromicPath(``int` `x, ``int` `y) ` `{ ` ` `  `    ``int` `lcaNode; ` ` `  `    ``// If both x and y are same then ` `    ``// lca will be the node itself ` `    ``if` `(x == y) ` `        ``lcaNode = x; ` ` `  `    ``// Find the lca of x and y ` `    ``else` `        ``lcaNode = LCA(1, x, y); ` ` `  `    ``int` `charactersCountFromXtoY[MAX_CHAR] = { 0 }; ` ` `  `    ``// Calculating the character count ` `    ``// for path node x to y ` `    ``for` `(``int` `i = 0; i < MAX_CHAR; i++) { ` `        ``charactersCountFromXtoY[i] ` `            ``= nodeCharactersCount[x][i] ` `              ``+ nodeCharactersCount[y][i] ` `              ``- 2 * nodeCharactersCount[lcaNode][i]; ` `    ``} ` ` `  `    ``// Checking if we can form the palindrome ` `    ``// string with the all character count ` `    ``if` `(canFormPalindrome(charactersCountFromXtoY)) ` `        ``return` `true``; ` `    ``return` `false``; ` `} ` ` `  `// Function to update character count at node v ` `void` `updateNodeCharactersCount(string str, ``int` `v) ` `{ ` ` `  `    ``// Updating the character count at node v ` `    ``for` `(``int` `i = 0; i < str.length(); i++) ` `        ``nodeCharactersCount[v][str[i] - ``'a'``]++; ` `} ` ` `  `// Function to perform the queries ` `void` `performQueries(vector > queries, ``int` `q) ` `{ ` `    ``int` `i = 0; ` `    ``while` `(i < q) { ` ` `  `        ``int` `x = queries[i]; ` `        ``int` `y = queries[i]; ` ` `  `        ``// If path can be a palindrome ` `        ``if` `(canFormPalindromicPath(x, y)) ` `            ``cout << ``"Yes\n"``; ` `        ``else` `            ``cout << ``"No\n"``; ` `        ``i++; ` `    ``} ` `} ` ` `  `// Driver code ` `int` `main() ` `{ ` ` `  `    ``// Fill the complete array with 0 ` `    ``memset``(nodeCharactersCount, 0, ` `           ``sizeof``(nodeCharactersCount)); ` ` `  `    ``// Edge between 1 and 2 labelled "bbc" ` `    ``tree.push_back(2); ` `    ``updateNodeCharactersCount(``"bbc"``, 2); ` ` `  `    ``// Edge between 1 and 3 labelled "ac" ` `    ``tree.push_back(3); ` `    ``updateNodeCharactersCount(``"ac"``, 3); ` ` `  `    ``// Update the character count ` `    ``// from root to the ith node ` `    ``buildTree(1); ` ` `  `    ``vector > queries{ { 1, 2 }, ` `                                  ``{ 2, 3 }, ` `                                  ``{ 3, 1 }, ` `                                  ``{ 3, 3 } }; ` `    ``int` `q = queries.size(); ` ` `  `    ``// Perform the queries ` `    ``performQueries(queries, q); ` ` `  `    ``return` `0; ` `} `

## Java

 `// Java implementation of the approach ` `import` `java.util.*; ` ` `  `@SuppressWarnings``(``"unchecked"``) ` `class` `GFG { ` ` `  `    ``static` `int` `MAX_SIZE = ``100005``, MAX_CHAR = ``26``; ` `    ``static` `int``[][] nodeCharactersCount = ``new` `int``[MAX_SIZE][MAX_CHAR]; ` ` `  `    ``static` `Vector[] tree = ``new` `Vector[MAX_SIZE]; ` ` `  `    ``// Function that returns true if a palindromic ` `    ``// string can be formed using the given characters ` `    ``static` `boolean` `canFormPalindrome(``int``[] charArray) { ` ` `  `        ``// Count odd occurring characters ` `        ``int` `oddCount = ``0``; ` `        ``for` `(``int` `i = ``0``; i < MAX_CHAR; i++) { ` `            ``if` `(charArray[i] % ``2` `== ``1``) ` `                ``oddCount++; ` `        ``} ` `        ``// Return false if odd count is more than 1, ` `        ``if` `(oddCount >= ``2``) ` `            ``return` `false``; ` `        ``else` `            ``return` `true``; ` `    ``} ` ` `  `    ``// Find to find the Lowest Common ` `    ``// Ancestor in the tree ` `    ``static` `int` `LCA(``int` `currentNode, ``int` `x, ``int` `y) { ` ` `  `        ``// Base case ` `        ``if` `(currentNode == x) ` `            ``return` `x; ` ` `  `        ``// Base case ` `        ``if` `(currentNode == y) ` `            ``return` `y; ` `        ``int` `xLca, yLca; ` ` `  `        ``// Initially value -1 denotes that ` `        ``// we need to find the ancestor ` `        ``xLca = yLca = -``1``; ` ` `  `        ``// -1 denotes that we need to find the lca ` `        ``// for x and y, values other than x and y ` `        ``// will be the LCA of x and y ` `        ``int` `gotLca = -``1``; ` ` `  `        ``// Iterating in the child ` `        ``// substree of the currentNode ` `        ``for` `(``int` `l = ``0``; l < tree[currentNode].size(); l++) { ` ` `  `            ``// Next node that will be checked ` `            ``int` `nextNode = tree[currentNode].elementAt(l); ` ` `  `            ``// Look for the next child subtree ` `            ``int` `out_ = LCA(nextNode, x, y); ` ` `  `            ``if` `(out_ == x) ` `                ``xLca = out_; ` `            ``if` `(out_ == y) ` `                ``yLca = out_; ` ` `  `            ``// Both the nodes exist in the different ` `            ``// subtrees, in this case parent node ` `            ``// will be the lca ` `            ``if` `(xLca != -``1` `&& yLca != -``1``) ` `                ``return` `currentNode; ` ` `  `            ``// Handle the cases where LCA is already ` `            ``// calculated or both x and y are present ` `            ``// in the same subtree ` `            ``if` `(out_ != -``1``) ` `                ``gotLca = out_; ` `        ``} ` `        ``return` `gotLca; ` `    ``} ` ` `  `    ``// Function to calculate the character count for ` `    ``// each path from node i to 1 (root node) ` `    ``static` `void` `buildTree(``int` `i) { ` `        ``for` `(``int` `l = ``0``; l < tree[i].size(); l++) { ` ` `  `            ``int` `nextNode = tree[i].elementAt(l); ` `            ``for` `(``int` `j = ``0``; j < MAX_CHAR; j++) { ` ` `  `                ``// Updating the character count ` `                ``// for each node ` `                ``nodeCharactersCount[nextNode][j] += nodeCharactersCount[i][j]; ` `            ``} ` ` `  `            ``// Look for the child subtree ` `            ``buildTree(nextNode); ` `        ``} ` `    ``} ` ` `  `    ``// Function that returns true if a palindromic path ` `    ``// is possible between the nodes x and y ` `    ``static` `boolean` `canFormPalindromicPath(``int` `x, ``int` `y) { ` ` `  `        ``int` `lcaNode; ` ` `  `        ``// If both x and y are same then ` `        ``// lca will be the node itself ` `        ``if` `(x == y) ` `            ``lcaNode = x; ` ` `  `        ``// Find the lca of x and y ` `        ``else` `            ``lcaNode = LCA(``1``, x, y); ` ` `  `        ``int``[] charactersCountFromXtoY = ``new` `int``[MAX_CHAR]; ` `        ``Arrays.fill(charactersCountFromXtoY, ``0``); ` ` `  `        ``// Calculating the character count ` `        ``// for path node x to y ` `        ``for` `(``int` `i = ``0``; i < MAX_CHAR; i++) { ` `            ``charactersCountFromXtoY[i] = nodeCharactersCount[x][i] +  ` `                                         ``nodeCharactersCount[y][i] ` `                               ``- ``2` `* nodeCharactersCount[lcaNode][i]; ` `        ``} ` ` `  `        ``// Checking if we can form the palindrome ` `        ``// string with the all character count ` `        ``if` `(canFormPalindrome(charactersCountFromXtoY)) ` `            ``return` `true``; ` `        ``return` `false``; ` `    ``} ` ` `  `    ``// Function to update character count at node v ` `    ``static` `void` `updateNodeCharactersCount(String str, ``int` `v) { ` ` `  `        ``// Updating the character count at node v ` `        ``for` `(``int` `i = ``0``; i < str.length(); i++) ` `            ``nodeCharactersCount[v][str.charAt(i) - ``'a'``]++; ` `    ``} ` ` `  `    ``// Function to perform the queries ` `    ``static` `void` `performQueries(``int``[][] queries, ``int` `q) { ` `        ``int` `i = ``0``; ` `        ``while` `(i < q) { ` ` `  `            ``int` `x = queries[i][``0``]; ` `            ``int` `y = queries[i][``1``]; ` ` `  `            ``// If path can be a palindrome ` `            ``if` `(canFormPalindromicPath(x, y)) ` `                ``System.out.println(``"Yes"``); ` `            ``else` `                ``System.out.println(``"No"``); ` `            ``i++; ` `        ``} ` `    ``} ` ` `  `    ``// Driver Code ` `    ``public` `static` `void` `main(String[] args) { ` ` `  `        ``// Fill the complete array with 0 ` `        ``for` `(``int` `i = ``0``; i < MAX_SIZE; i++) { ` `            ``for` `(``int` `j = ``0``; j < MAX_CHAR; j++) { ` `                ``nodeCharactersCount[i][j] = ``0``; ` `            ``} ` `        ``} ` `        ``for` `(``int` `i = ``0``; i < MAX_SIZE; i++) { ` `            ``tree[i] = ``new` `Vector<>(); ` `        ``} ` ` `  `        ``// Edge between 1 and 2 labelled "bbc" ` `        ``tree[``1``].add(``2``); ` `        ``updateNodeCharactersCount(``"bbc"``, ``2``); ` ` `  `        ``// Edge between 1 and 3 labelled "ac" ` `        ``tree[``1``].add(``3``); ` `        ``updateNodeCharactersCount(``"ac"``, ``3``); ` ` `  `        ``// Update the character count ` `        ``// from root to the ith node ` `        ``buildTree(``1``); ` ` `  `        ``int``[][] queries = { { ``1``, ``2` `}, { ``2``, ``3` `}, { ``3``, ``1` `}, { ``3``, ``3` `} }; ` `        ``int` `q = queries.length; ` ` `  `        ``// Perform the queries ` `        ``performQueries(queries, q); ` `    ``} ` `} ` ` `  `// This code is contributed by ` `// sanjeev2552 `

Output:

```Yes
Yes
No
Yes
```

Don’t stop now and take your learning to the next level. Learn all the important concepts of Data Structures and Algorithms with the help of the most trusted course: DSA Self Paced. Become industry ready at a student-friendly price.

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 : sanjeev2552

Article Tags :
Practice Tags :

2

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.