Codility挑战 - 为什么这个解决方案有效?

时间:2017-05-05 09:15:23

标签: c algorithm palindrome anagram

问题:

给定一串数字,计算任何回文字符的子字数(一致子序列)。

示例:

对于输入字符串“02002”,结果应为11,即:

“0”,“2”,“0”,“0”,“2”,“00”,“020”,“200”,“002”,“2002”,“02002”

我可以看到下面的解决方案有效,但我无法理解为什么。特别是我不明白内循环的意义。任何人都可以解释这背后的逻辑吗?

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define M 1000000007
#define COLORS 10
#define SUBSETS (1 << (COLORS))

int solution(char *S) {
    int len, result;
    int *values;
    int v, idx, middle, mask;

    result = 0;
    values = calloc(SUBSETS, sizeof(int));
    //new_values = calloc(SUBSETS, sizeof(int));
    len = strlen(S);
    mask = 0;

    for (idx = 0; idx < len; idx++) {
        v = S[idx] - '0';
        mask ^= (1 << v);
        values[mask ^ (1 << v)] += 1;
        result = (result + values[mask]) % M;
        for (middle = 0;  middle < COLORS; middle++) {
            result = (result + values[mask ^ (1 << middle)]) % M;
        }
    }
    return result;
}

如果需要,请提供更多详细信息:https://codility.com/programmers/task/winter_lights/

1 个答案:

答案 0 :(得分:1)

对于您要计算idx的每个iiidx的灯光可以构成回文。这意味着每种类型的灯都有偶数个,或者除了一个(位于回文中间)之外,所有灯都是偶数个。

代码使用技巧来计算i,以避免O(n ^ 2)行为。在处理索引idx的灯光后,数组values包含每个mi<idx的数量,使得灯光序列从0到{{1}包含每个灯的偶数或奇数(取决于i的位)。例如,m包含灯的初始序列的数量(最多values[3],其中奇数个灯0和1,以及偶数个其他灯。)

使用此数组,计算以idx结尾的混洗回文很容易:如果最多idx的掩码为idx,那么所有灯数均为偶数的回文数与具有相同掩码的左序列的数量相同(即:mask)。类似地,除偶数个灯(values[mask])外,具有偶数个灯的回文数量与具有掩码middle的左序列数相同。