[洛谷P4503][CTSC2014]企鹅QQ
题目大意:给你$n(n\leqslant3\times10^4)$个长度为$l(l\leqslant200)$的字符串,要你求出有多少对字符串是相似的,相似的定义是两个字符串只在一位上不同。
题解:可以对每一位求出去掉这一位后的字符串$hash$值,发现直接算可能有点烦,考虑异或的自反性($a\oplus b\oplus a=b$),可以在$hash$时把每一位的结果异或起来,求扣除一位的$hash$值时只需要再异或上这一位即可。
用异或的话,需要给每一位一个权值,可以直接$rand$求出。
最后给存扣除每一位的数组排一个序,找其中相同的元素个数即可。
卡点:无
C++ Code:
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#define maxn 30010
#define maxl 210
inline unsigned long long randllu() { return static_cast<unsigned long long> (rand()); }
inline unsigned long long RAND() {
return randllu() << 48 ^ randllu() << 32 ^ randllu() << 16 ^ randllu();
}
int n, l, ans;
unsigned long long len[256], str[256];
std::vector<unsigned long long> v[maxl];
int main() {
srand(20040826);
scanf("%d%d%*d", &n, &l);
for (int i = 0; i < 256; ++i) {
len[i] = RAND();
str[i] = RAND();
}
for (int i = 1; i <= n; ++i) {
static char s[maxl];
scanf("%s", s);
unsigned long long hsh = 0;
for (int i = 0; i < l; ++i) hsh ^= len[i] * str[s[i]];
for (int i = 0; i < l; ++i) v[i].push_back(hsh ^ len[i] * str[s[i]]);
}
for (int len = 0; len < l; ++len) {
std::vector<unsigned long long> &V = v[len];
std::sort(V.begin(), V.end());
for (std::vector<unsigned long long>::iterator l = V.begin(); l != V.end(); ) {
unsigned long long ch = *l;
int now = 0;
while (l != V.end() && *l == ch) ++l, ans += now++;
}
}
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号