You are given a tree (i.e. a connected, undirected graph that has no cycles) rooted at node 0 consisting of n nodes numbered from 0 to n - 1. The tree is represented by a 0-indexed array parent of size n, where parent[i] is the parent of node i. Since node 0 is the root, parent[0] == -1.
You are also given a string s of length n, where s[i] is the character assigned to the edge between i and parent[i]. s[0] can be ignored.
Return the number of pairs of nodes (u, v) such that u < v and the characters assigned to edges on the path from u to v can be rearranged to form a palindrome.
A string is a palindrome when it reads the same backwards as forwards.
Example 1:

Input: parent = [-1,0,0,1,1,2], s = "acaabc" Output: 8 Explanation: The valid pairs are: - All the pairs (0,1), (0,2), (1,3), (1,4) and (2,5) result in one character which is always a palindrome. - The pair (2,3) result in the string "aca" which is a palindrome. - The pair (1,5) result in the string "cac" which is a palindrome. - The pair (3,5) result in the string "acac" which can be rearranged into the palindrome "acca".
Example 2:
Input: parent = [-1,0,0,0,0], s = "aaaaa" Output: 10 Explanation: Any pair of nodes (u,v) where u < v is valid.
Constraints:
n == parent.length == s.length1 <= n <= 1050 <= parent[i] <= n - 1 for all i >= 1parent[0] == -1parent represents a valid tree.s consists of only lowercase English letters.We can use a Depth First Search (DFS) approach combined with a bitmask to efficiently determine if the characters along a path can be rearranged into a palindrome. The idea is as follows:
This Python solution uses DFS to navigate through the tree starting from the root node. We maintain a bitmask `path` that helps track character parity. For any given node to node path within the tree, the XOR of their paths determines if the characters can form a palindrome. The usage of memoization via the `memo` dictionary helps in efficiently checking these conditions for all node pairs.
C++
Time Complexity: O(n), where n is the number of nodes because each node and each edge in the tree is visited once.
Space Complexity: O(n), for storing the tree structure and the memoization dictionary.
Another approach to solve this problem is using dynamic programming on trees. The idea is to precompute some information at each node that helps in determining the palindromic nature of any two nodes quickly.
The Java solution uses dynamic programming to calculate character frequency masks for each node. This mask is then used to determine palindromic potential between any two nodes. While dynamic programming is used, the main palindromic check still hinges on bit manipulation to quickly assess parity conditions between nodes.
C#
Time Complexity: Although we precompute data, combining this with the mask checking gives an overall complexity similar to O(n^2).
Space Complexity: O(n), for storing precomputed masks and the map of frequency masks.
| Approach | Complexity |
|---|---|
| DFS with Bitmask for Palindrome Check | Time Complexity: O(n), where n is the number of nodes because each node and each edge in the tree is visited once. |
| Dynamic Programming on Tree | Time Complexity: Although we precompute data, combining this with the mask checking gives an overall complexity similar to O(n^2). |
How to solve (almost) any binary tree coding problem • Inside code • 224,588 views views
Watch 9 more video solutions →Practice Count Paths That Can Form a Palindrome in a Tree with our built-in code editor and test cases.
Practice on FleetCode