Longest Path With Different Adjacent Characters

hard tree dp dfs

Problem

You have a tree of n nodes rooted at node 0, given as a parent array where parent[i] is the parent of node i (and parent[0] = -1), plus a string s where s[i] is the lowercase letter written on node i.

Find the longest path in the tree such that no two adjacent nodes on the path carry the same letter, and return its length counted in nodes.

Inputparent = [-1,0,0,1,1,2], s = "abacbe"
Output3
One longest path is 3 → 1 → 0 with letters c, b, a — no two neighbouring letters match, and every path of 4 or more nodes repeats a letter somewhere.

def longest_path(parent, s):
    n = len(parent)
    children = [[] for _ in range(n)]
    for i in range(1, n):
        children[parent[i]].append(i)
    ans = 1

    def dfs(u):
        nonlocal ans
        best1 = best2 = 0
        for v in children[u]:
            chain = dfs(v)
            if s[v] != s[u]:
                if chain > best1:
                    best1, best2 = chain, best1
                elif chain > best2:
                    best2 = chain
        ans = max(ans, best1 + best2 + 1)
        return best1 + 1

    dfs(0)
    return ans
function longestPath(parent, s) {
  const n = parent.length;
  const children = Array.from({ length: n }, () => []);
  for (let i = 1; i < n; i++) children[parent[i]].push(i);
  let ans = 1;

  function dfs(u) {
    let best1 = 0, best2 = 0;
    for (const v of children[u]) {
      const chain = dfs(v);
      if (s[v] !== s[u]) {
        if (chain > best1) { best2 = best1; best1 = chain; }
        else if (chain > best2) best2 = chain;
      }
    }
    ans = Math.max(ans, best1 + best2 + 1);
    return best1 + 1;
  }

  dfs(0);
  return ans;
}
class Solution {
    List<List<Integer>> children;
    String s;
    int ans = 1;

    public int longestPath(int[] parent, String s) {
        int n = parent.length;
        this.s = s;
        children = new ArrayList<>();
        for (int i = 0; i < n; i++) children.add(new ArrayList<>());
        for (int i = 1; i < n; i++) children.get(parent[i]).add(i);
        dfs(0);
        return ans;
    }

    int dfs(int u) {
        int best1 = 0, best2 = 0;
        for (int v : children.get(u)) {
            int chain = dfs(v);
            if (s.charAt(v) != s.charAt(u)) {
                if (chain > best1) { best2 = best1; best1 = chain; }
                else if (chain > best2) best2 = chain;
            }
        }
        ans = Math.max(ans, best1 + best2 + 1);
        return best1 + 1;
    }
}
class Solution {
public:
    int longestPath(vector<int>& parent, string s) {
        int n = parent.size();
        vector<vector<int>> children(n);
        for (int i = 1; i < n; i++) children[parent[i]].push_back(i);
        int ans = 1;
        function<int(int)> dfs = [&](int u) {
            int best1 = 0, best2 = 0;
            for (int v : children[u]) {
                int chain = dfs(v);
                if (s[v] != s[u]) {
                    if (chain > best1) { best2 = best1; best1 = chain; }
                    else if (chain > best2) best2 = chain;
                }
            }
            ans = max(ans, best1 + best2 + 1);
            return best1 + 1;
        };
        dfs(0);
        return ans;
    }
};
Time: O(n) Space: O(n)