问题:
给定一串数字,计算任何回文字符的子字数(一致子序列)。
示例:
对于输入字符串“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/。
答案 0 :(得分:1)
对于您要计算idx
的每个i
,i
到idx
的灯光可以构成回文。这意味着每种类型的灯都有偶数个,或者除了一个(位于回文中间)之外,所有灯都是偶数个。
代码使用技巧来计算i
,以避免O(n ^ 2)行为。在处理索引idx
的灯光后,数组values
包含每个m
,i<idx
的数量,使得灯光序列从0到{{1}包含每个灯的偶数或奇数(取决于i
的位)。例如,m
包含灯的初始序列的数量(最多values[3]
,其中奇数个灯0和1,以及偶数个其他灯。)
使用此数组,计算以idx
结尾的混洗回文很容易:如果最多idx
的掩码为idx
,那么所有灯数均为偶数的回文数与具有相同掩码的左序列的数量相同(即:mask
)。类似地,除偶数个灯(values[mask]
)外,具有偶数个灯的回文数量与具有掩码middle
的左序列数相同。