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 node i.

Return the length of the longest path in the tree such that no pair of adjacent nodes on the path have the same character assigned to them.

&nbsp;
Example 1:

Input: parent = [-1,0,0,1,1,2], s = "abacbe"
Output: 3
Explanation: The longest path where each two adjacent nodes have different characters in the tree is the path: 0 -&gt; 1 -&gt; 3. The length of this path is 3, so 3 is returned.
It can be proven that there is no longer path that satisfies the conditions. 


Example 2:

Input: parent = [-1,0,0,0], s = "aabc"
Output: 3
Explanation: The longest path where each two adjacent nodes have different characters is the path: 2 -&gt; 0 -&gt; 3. The length of this path is 3, so 3 is returned.


&nbsp;
Constraints:


	n == parent.length == s.length
	1 &lt;= n &lt;= 105
	0 &lt;= parent[i] &lt;= n - 1 for all i &gt;= 1
	parent[0] == -1
	parent represents a valid tree.
	s consists of only lowercase English letters.


class Solution:
    def longestPath(self, parent: list[int], s: str) -> int:
        def l_path_and_chain(tree: dict[int, list[int]], s: str, root: int) -> tuple[int, int]:
            lp = lc1 = lc2 = 0
            for child, path, chain in ((c, *l_path_and_chain(tree, s, c)) for c in tree[root]):
                lp = max(lp, path)
                if s[child] != s[root]: *_, lc2, lc1 = sorted((chain, lc2, lc1))

            return max(lp, lc1 + lc2 + 1), lc1 + 1

        t = defaultdict(list)
        for c, p in enumerate(parent): t[p].append(c)
        return l_path_and_chain(t, s, 0)[0]
class Solution {
    int longestPathValue = 1; // variable to store the length of the longest path

    public int longestPath(int[] parent, String s) {
        // create an adjacency list representation of the tree
        Map<Integer, List<Integer>> adj = new HashMap<>();
        for(int i = 1; i < parent.length; i++){
            int j = parent[i];
            adj.putIfAbsent(j, new LinkedList<>());
            adj.get(j).add(i);
        }
        // call dfs on the root of the tree
        dfs(0, adj, s);
        return longestPathValue;
    }

    public int dfs(int node, Map<Integer, List<Integer>> adj, String s){
        // if the node is a leaf node, return 1
        if(!adj.containsKey(node)) return 1;
        int max = 0, secondMax = 0;
        // for each neighbor of the node
        for(int nbrNode : adj.get(node)){
            int longestPathFromNbrNode = dfs(nbrNode , adj, s);
            // if the characters at the current node and its neighbor are the same, ignore the neighbor
            if(s.charAt(node) == s.charAt(nbrNode)) continue;
            // update max and secondMax with the longest path from the neighbor node
            if(longestPathFromNbrNode > max){
                secondMax = max;
                max = longestPathFromNbrNode;
            }else if(longestPathFromNbrNode > secondMax){
                secondMax = longestPathFromNbrNode;
            }
        }
        // update longestPathValue with the longest path that includes the current node
        longestPathValue = Math.max(longestPathValue, max+secondMax+1);
        return max+1;
    }
}
class Solution {
public:
    vector<vector<int>>g;
    int ans=0;
   int dfs(int node,int par, string &s){
       // vector to store max length & second max length that we get from children of node at v[1] & v[0] respectively
        vector<int>v(2,0);
       for(auto child:g[node]){
           if(child != par){
               int x = dfs(child,node,s);
			   // if char at node != char at child then node can be included in our ans
               if(s[node] != s[child]){
                   if(v[1]<x){
                       v[0]=v[1];
                       v[1]=x;
                       
                   }else{
                       v[0]=max(v[0],x);
                   }
               }
               
           }
       }
       // update our ans every time we return to node
       ans = max(ans, v[0]+v[1]+1);
	   //return the max length up till here including node
       return max(v[0],v[1])+1;
        
    }
    int longestPath(vector<int>& parent, string s) {
        int n = s.size();
        
        ans =0;
        g.assign(n+1,{});
        for(int i=1;i<parent.size();i++){
           g[parent[i]].push_back(i);
           g[i].push_back(parent[i]);
        }
		// run dfs and calculate max 
        ans = max(ans, dfs(0,-1,s));
        return ans;
        
    }
};
var longestPath = function(parent, s) {
  const adjList = parent.reduce((adjList, parent, node) => {
    if (parent < 0) return adjList;
    adjList[parent].push(node);
    return adjList;
  }, new Array(parent.length).fill(0).map(() => []));
  
  let longest = 1;
  
  const getLongest = (node) => {
    let maxChild1 = 0;
    let maxChild2 = 0;
    
    adjList[node].forEach((child) => {
      const childLength = getLongest(child);
    
	  // child letter matches our node, so we can't use it
      if (s[child] === s[node]) return;
      
	  // compare and update the longest two child paths
      if (childLength > maxChild1) {
        maxChild2 = maxChild1;
        maxChild1 = childLength;
      } else if (childLength > maxChild2) {
        maxChild2 = childLength;
      }
    });
    
	// longest loop
    longest = Math.max(longest, maxChild1 + maxChild2 + 1);
    
	// return longest path up the tree
    return 1 + maxChild1;
  }
  
  getLongest(0);
  
  return longest;
};
Longest Path With Different Adjacent Characters