2023-07-24 355场 周赛 T4

95 阅读1分钟

Problem: 2791. 树中可以形成回文的路径数

思路

由于只有26个字母,可以利用二进制表示,而是否能构成回文串取决于出现奇数频次的字符

解题方法

两个节点V->W的路径的异或之和,相当于V-> LCA, LCA->W,LCA为它们的公共祖先,进而为了方便,V->Root & Root->W的异或之和,由于共同部分可以抵消,因此这样子可以减少计算,只需分别计算Root到各个节点的XOR值,并记录到Map中即可。

Code


class Solution {
    private List<int[]>[] g;
    private Map<Integer, Integer> cnts;
    private long res;

    public long countPalindromePaths(List<Integer> parent, String s) {
        int n = parent.size();
        this.g = new ArrayList[n];
        Arrays.setAll(g, k -> new ArrayList<>());
        for (int i = 1; i < n; ++i) {
            g[parent.get(i)].add(new int[] { i, 1 << (s.charAt(i) - 'a' )});
            // g[i][0] 节点, g[i][1] 对应字符
        }
        this.cnts = new HashMap<>();
        dfs(0, 0);
        return res; 
    }
    // 统计根节点到每个节点的XOR值
    private void dfs(int x, int xor) {
        res += cnts.getOrDefault(xor, 0);
        // 统计异或值相同的节点
        for (int i = 0; i < 26; ++i) {
            res += cnts.getOrDefault(xor ^ (1 << i), 0);
        }
        // 统计异或值为2的整数幂的节点
        
        cnts.put(xor, cnts.getOrDefault(xor, 0) + 1);
        // 记录每个异或值得出现频次
        for (int[] neighbor : g[x]) {
            int y = neighbor[0];
            int m = neighbor[1];
            dfs(y, xor ^ m); // 从根节点到y的 XOR值
        }
    }
}