zoukankan      html  css  js  c++  java
  • 入门oj6489:文章评分(hash)

    题目

    Description

    nodgd的文章由n个小写英文字母组成。文章的一个子串指的是文章中的一段连续的字母,子串的长度就是这一段的字母个数。nodgd在文章中用了排比、对偶、前后照应之类的手法,所以就有很多个子串是相同或者相近的。为了向大家证明这是一篇好文章,nodgd决定给自己的文章进行评分。nodgd 首先确定了一个整数m,然后统计出文章中有多少个不相同的长度为m的子串,这个数量就是文章的评分。

    Input

    第一行包含两个整数n,m,表示文章的长度和需要统计的子串长度。
    1≤m≤n≤200000
    第二行包含一个长度为n的只包含小写字母的字符串。

    Output

    一行一个整数,表示文章的评分。

    Sample Input

    5 3 
    aaaab

    Sample Output

    2
    【提示】
    【样例解释1】
    长度为3的子串有3个,分别是 aaa,aaa,aab,其中不同的只有2个。

    HINT


     

    思路:

    一道很明显的hash题,我们可以用map来存每一个字串的hash值,再看有多少个不同的;

    由于oj的数据强化了,所以要用双hash,但蒟蒻博主用双hash却和数据的答案有几个数的相差;

    所以,博主用了三hash就过了;

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f;
    }
    const int mod=19260819,mod1=19260809,mod2=19260719;//防止数据过大的mod 
    ll p[1000001],p1[1000001],p2[1000001],ha[1000001],ha1[1000001],ha2[1000001];
    ll b=193,b1=137,b2=107;//每个hash值的进制   三hash 
    ll n,m;
    map<ll,bool> a,a1,a2;
    char c[1000001];
    int main()
    {
        //不懂的去网上看hash基础,或私聊博主 
        p[0]=1;p1[0]=1;p2[0]=1;
        for(ll i=1;i<=1000001;i++)
            p[i]=p[i-1]*b%mod,
            p1[i]=p1[i-1]*b1%mod1,
            p2[i]=p2[i-1]*b2%mod2;//记录每一位上转进制时要乘的数 
        n=read();m=read();
        scanf("%s",(c+1));
        for(ll i=1;i<=n;i++)
            ha[i]=(ha[i-1]*b%mod+(c[i]-'A'+1))%mod,
            ha1[i]=(ha1[i-1]*b1%mod1+(c[i]-'A'+1))%mod1,
            ha2[i]=(ha2[i-1]*b2%mod2+(c[i]-'A'+1))%mod2;//把每一位上的hash值求出来 
        ll ans=0;
        for(ll i=1;i<=n-m+1;i++)//枚举每一个题目要求长度的字串 
        {
            ll t=((ha[i+m-1]-ha[i-1]*p[m]%mod)+mod)%mod;
            ll tt=((ha1[i+m-1]-ha1[i-1]*p1[m]%mod1)+mod1)%mod1;
            ll ttt=((ha2[i+m-1]-ha2[i-1]*p2[m]%mod2)+mod2)%mod2;//把字串的不同hash值求出 
            if(!a[t]||!a1[tt]||!a2[ttt])//如果没有出现过就ans++ 
                ans++;
            a[t]=1,a1[tt]=1,a2[ttt]=1;
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    两步验证杀手锏:Java 接入 Google 身份验证器实战
    涨姿势:Spring Boot 2.x 启动全过程源码分析
    Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!
    Spring Boot 2.x 启动全过程源码分析(上)入口类剖析
    推荐:7 月份值得一看的 Java 技术干货!
    屌炸天,Oracle 发布了一个全栈虚拟机 GraalVM,支持 Python!
    Spring Boot 核心配置文件 bootstrap & application 详解。
    出场率比较高的一道多线程安全面试题
    凉凉了,Eureka 2.x 停止维护,Spring Cloud 何去何从?
    读写Excel
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/12991457.html
Copyright © 2011-2022 走看看