【bzoj3555】[Ctsc2014]企鹅QQ 简单哈希

传送门

题目分析

题意即求有多少对字符串只相差一个字符,枚举删除每个字符后的哈希, 看有多少相等即可。

比如有如下字符串:$Sd123$,其中S部分的哈希值为H,删除的是d,则原字符串的哈希值为$$(((H * T + d) * T + 1) * T + 2) * T + 3 = H * T^4 + d * T^3 + 1 * T^2 + 2 * T + 3$$

删除过后就为$$((H * T + 1) * T + 2) * T +3 = H * T^3 + 1 * T^2 + 2 * T + 3$$

也就是将1以前的哈希值全部剪去然后加上d之前的哈希值乘以$T^{len - delpos}$。

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

const int N = 3e4 + 5, L = 205, Mod = 23333;
typedef unsigned long long ull;
const ull H = 149;
ull hash[N][L], poww[L], go[N << 2], t[N];
int ecnt, adj[Mod + 5], nxt[N << 2];
int n, l, m, cnt;
char s[N][L];

inline ull del(int k, int d){
    return hash[k][l] - hash[k][d] * poww[l - d] + hash[k][d - 1] * poww[l - d];
}

int main(){
    scanf("%d%d%d", &n, &l, &m);
    for(int i = 1; i <= n; i++)
        scanf("%s", s[i] + 1);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= l; j++)
            hash[i][j] = hash[i][j - 1] * H + s[i][j];
    poww[0] = 1;
    for(int i = 1; i <= L; i++) poww[i] = poww[i - 1] * H;
    for(int j = 1; j <= l; j++){
        for(int i = 1; i <= n; i++)
            t[i] = del(i, j);
        sort(t + 1,t + n + 1);
        int sum = 1;
        for(int i = 2; i <= n; i++){
            if(t[i] == t[i - 1]){
                cnt += sum;
                sum++;
            }
            else sum = 1;
        }
    }
    printf("%d", cnt);
    return 0;
}
时间: 2024-10-05 06:30:06

【bzoj3555】[Ctsc2014]企鹅QQ 简单哈希的相关文章

bzoj3555[Ctsc2014]企鹅QQ

bzoj3555[Ctsc2014]企鹅QQ 题意: 判定有多少对字符串只有一个字母不同.字符串个数≤30000,长度≤300. 题解: 求出第i个字符串前j个字符的哈希值hs[i][j],然后枚举去掉所有字符串的第几位,将去掉后的字符串的哈希值用hs数组直接算出,排序后检查有没有相同的计入答案. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k

BZOJ 3555: [Ctsc2014]企鹅QQ [字符串哈希]【学习笔记】

3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 2046  Solved: 749[Submit][Status][Discuss] Description PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大的互联网功能体验,满足用户对社交.资讯.娱乐.交易等多方面的需求.小Q是Pe

【字符串哈希】bzoj3555 [Ctsc2014]企鹅QQ

枚举每个位置,给每个串的前半部分一个哈希值,后半部分一个哈希值,若是它们均相等,则视为这两个串相似. 每次转移之后,排序一下就行了. O(L*n*log(n)). #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef unsigned long long ull; struct HASH{ull l,r;}h

BZOJ3555 [Ctsc2014]企鹅QQ 题解

题目大意: 有一些字符串,求其中两个等长且恰好只有一位不同的字符串的对数. 思路: Hash大法好!正着倒着各来一遍(底数不同),之后枚举不同的那一位,前后两段拼起来之后为了有区分前面一部分再乘一个数.模数用unsigned long long自然溢出. 代码: 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int S1=1007,

bzoj3555: [Ctsc2014]企鹅QQ (Hash)

枚举每个分段的点,每次O(n)更新左边和右边的hash值 然后用双指针O(n)计算答案 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<iostream> 5 #define ull unsigned long long 6 using namespace std; 7 struct HS{ 8 ull l,r; 9 }tmp[30010],hs[30010]

BZOJ3555 [Ctsc2014]企鹅QQ 【hash】

题目 PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大的互联网功能体验,满足用户对社交.资讯.娱乐.交易等多方面的需求. 小Q是PenguinQQ网站的管理员,他最近在进行一项有趣的研究--哪些账户是同一个人注册的.经过长时间的分析,小Q发现同一个人注册的账户名称总是很相似的,例如Penguin1,Penguin2,Penguin3--于是小Q决定先对这种相似的情形进行

【题解】P4503 [CTSC2014]企鹅QQ(哈希)

[题解]P4503 [CTSC2014]企鹅QQ(哈希) 考虑这样一种做法,将每个字符串的删去某个字符的新字符串的哈希值存下来,然后最后\(sort\)一遍双指针统计每个值相同的数的个数\(x\),这个\(x\)对答案的贡献是\({x \choose 2}\) //@winlere #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace

3555: [Ctsc2014]企鹅QQ

3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 696  Solved: 294[Submit][Status][Discuss] Description PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大的互联网功能体验,满足用户对社交.资讯.娱乐.交易等多方面的需求.小Q是Pen

bzoj——3555: [Ctsc2014]企鹅QQ

3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 2617  Solved: 921[Submit][Status][Discuss] Description PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大的互联网功能体验,满足用户对社交.资讯.娱乐.交易等多方面的需求.小Q是Pe