You are given a tree rooted at node 0, consisting of n nodes numbered from 0 to n - 1. The tree is represented by an 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 node i.
Consider an empty string dfsStr, and define a recursive function dfs(int x) that takes a node x as a parameter and performs the following steps in order:
Iterate over each child y of xin increasing order of their numbers, and call dfs(y).
Add the character s[x] to the end of the string dfsStr.
Note that dfsStr is shared across all recursive calls of dfs.
You need to find a boolean array answer of size n, where for each index i from 0 to n - 1, you do the following:
Empty the string dfsStr and call dfs(i).
If the resulting string dfsStr is a palindrome, then set answer[i] to true. Otherwise, set answer[i] to false.
Return the array answer.
Example 1:
Input:parent = [-1,0,0,1,1,2], s = "aababa"
Output:[true,true,false,true,true,true]
Explanation:
Calling dfs(0) results in the string dfsStr = "abaaba", which is a palindrome.
Calling dfs(1) results in the string dfsStr = "aba", which is a palindrome.
Calling dfs(2) results in the string dfsStr = "ab", which is not a palindrome.
Calling dfs(3) results in the string dfsStr = "a", which is a palindrome.
Calling dfs(4) results in the string dfsStr = "b", which is a palindrome.
Calling dfs(5) results in the string dfsStr = "a", which is a palindrome.
Example 2:
Input:parent = [-1,0,0,0,0], s = "aabcb"
Output:[true,true,true,true,true]
Explanation:
Every call on dfs(x) results in a palindrome string.
Constraints:
n == parent.length == s.length
1 <= n <= 105
0 <= parent[i] <= n - 1 for all i >= 1.
parent[0] == -1
parent represents a valid tree.
s consists only of lowercase English letters.
Solutions
Solution 1: DFS + String Hashing
Thinking
The \(\textit{dfsStr}\) of a subtree is a contiguous segment, and we must test whether it is a palindrome. With \(n \le 10^5\) we cannot rescan the string at every node.
One DFS writes the whole-tree \(\textit{dfsStr}\) and records the interval \([l, r]\) of each node.
Hashes of the string and of its reverse let us compare the first half of \([l, r]\) with the corresponding half of the reverse in \(O(1)\), which decides palindromicity.
We can use Depth-First Search (DFS) to traverse the tree and compute the entire \(\textit{dfsStr}\), while also determining the interval \([l, r]\) for each node.
Then, we use string hashing to compute the hash values of both \(\textit{dfsStr}\) and the reverse of \(\textit{dfsStr}\) to check if it is a palindrome.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the length of the string \(s\).
The \(\textit{dfsStr}\) of a subtree is a contiguous segment, and we must test whether it is a palindrome. With \(n \le 10^5\), rescanning the string at every node is \(O(n^2)\), and writing the traversal by recursion from the root is too deep: a chain makes the call depth \(n\).
A node's character is appended only when the node is left, so its interval covers exactly the descendants written first. Children have to be processed in the adjacency-list order, or the endpoints will not match the recursive traversal.
An explicit stack of \((node, state)\) runs that postorder. On entry we push the exit marker and then the children in reverse, so they still pop from left to right, and on exit we record \([l, r]\). Hashes of the string and of its reverse compare the first half of \([l, r]\) with the matching half of the reverse in \(O(1)\).
An explicit stack walks the tree in postorder. When a node is left, its character is appended to \(\textit{dfsStr}\) and its interval \([l, r]\) is recorded. Children are processed from left to right in the adjacency list.
Then, we use string hashing to compute the hash values of both \(\textit{dfsStr}\) and the reverse of \(\textit{dfsStr}\) to check whether each interval is a palindrome.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the length of the string \(s\).