zoukankan      html  css  js  c++  java
  • 【BZOJ 3555】 [Ctsc2014]企鹅QQ(哈希)

    Description


    PenguinQQ是中国最大、最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志、群、即时通讯、相册、集市等丰富强大的互联网功能体验,满足用户对社交、资讯、娱乐、交易等多方面的需求。
    小Q是PenguinQQ网站的管理员,他最近在进行一项有趣的研究——哪些账户是同一个人注册的。经过长时间的分析,小Q发现同一个人注册的账户名称总是很相似的,例如Penguin1,Penguin2,Penguin3……于是小Q决定先对这种相似的情形进行统计。
    小Q定义,若两个账户名称是相似的,当且仅当这两个字符串等长且恰好只有一位不同。例如“Penguin1”和“Penguin2”是相似的,但“Penguin1”和“2Penguin”不是相似的。而小Q想知道,在给定的 个账户名称中,有多少对是相似的。
    为了简化你的工作,小Q给你的 个字符串长度均等于 ,且只包含大小写字母、数字、下划线以及‘@’共64种字符,而且不存在两个相同的账户名称。

    Input


    第一行包含三个正整数 , , 。其中 表示账户名称数量, 表示账户名称长度, 用来表示字符集规模大小,它的值只可能为2或64。
    若 等于2,账户名称中只包含字符‘0’和‘1’共2种字符;
    若 等于64,账户名称中可能包含大小写字母、数字、下划线以及‘@’共64种字符。
    随后 行,每行一个长度为 的字符串,用来描述一个账户名称。数据保证 个字符串是两两不同的。

    Output


    仅一行一个正整数,表示共有多少对相似的账户名称。

    Sample Input

    4 3 64
    Fax
    fax
    max
    mac
    

    Sample Output

    4
    

    HINT


    4对相似的字符串分别为:Fax与fax,Fax与max,fax与max,max与mac。N<=30000,L<=200,S<=64

    题解


    预处理所有位置把字符串分成两个部分,把这两个部分哈希成一个数字。
    之后枚举一个位置之后在把两个数字利用哈希连接起来,存进一个数组,数一数有多少个一样的就行了
    PS:发现不使用unsigned long long也行,long long溢出后变成负数也是没问题的,同样也是一个循环,和取模,无符号溢出没啥区别。

    #include <map>
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <complex>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define inf 1000000000
    #define PI acos(-1)
    #define bug puts("here")
    #define REP(i,x,n) for(int i=x;i<=n;i++)
    #define DEP(i,n,x) for(int i=n;i>=x;i--)
    #define mem(a,x) memset(a,x,sizeof(a))
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void Out(ll a){
        if(a<0) putchar('-'),a=-a;
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=3e4+5;
    char s[300];
    ll ha1[N][300],ha2[N][300];
    ll p1[N],p2[N];
    ll a[N];
    int main(){
        int n=read(),m=read(),sigma=read();
        p1[0]=p2[0]=1;
        int seed1=123,seed2=233,seed3=1789;;
        REP(i,1,n) p1[i]=p1[i-1]*seed1,p2[i]=p2[i-1]*seed2;
        REP(i,1,n){
            scanf("%s",s+1);
            REP(j,1,m)
                ha1[i][j]=ha1[i][j-1]+p1[j-1]*s[j];
            DEP(j,m,1)
                ha2[i][j]=ha2[i][j+1]+p2[m-j]*s[j];
        }
        int ans=0;
        REP(i,1,m){
            REP(j,1,n){
                a[j]=ha1[j][i-1]*seed3+ha2[j][i+1];
            }
            sort(a+1,a+1+n);
            int sum=1;
            REP(j,2,n){
                if(a[j]==a[j-1]) ans+=sum,sum++;
                else sum=1;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    GITHUB随笔 15-5月 junit
    github心得
    (转)哪个瞬间让你突然觉得逛知乎真有用?
    0-1背包问题(the knapsack problem)
    对VSCode在安装了Dev-cpp的电脑上的配置
    非全日制考研资料(未完待续)
    CSS那些事读书笔记-2
    CSS那些事读书笔记-1
    前端面试准备-1
    工作日记-一个有趣的定时任务实现
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/7504955.html
Copyright © 2011-2022 走看看