• 简单 hash 入门题目


    题目描述

    NOIP 复赛之前,HSD 桑进行了一项研究,发现人某条染色体上的一段 DNA 序列中连续的 kkk 个碱基组成的碱基序列与做题的 AC 率有关!于是他想研究一下这种关系。
    现在给出一段 DNA 序列,请帮他求出这段 DNA 序列中所有连续 kkk 个碱基形成的碱基序列中,出现最多的一种的出现次数。

    输入格式

    两行,第一行为一段 DNA 序列,保证 DNA 序列合法,即只含有 A, G, C, T 四种碱基;
    第二行为一个正整数 kkk,意义与题目描述相同。

    输出格式

    一行,一个正整数,为题目描述中所求答案。

    样例

    样例输入 1

    AAAAA
    1

    样例输出 1

    5

    样例解释 1

    对于这段 DNA 序列,连续的 111 个碱基组成的碱基序列只有 A,共出现 555 次,所以答案为 555。

    样例输入 2

    ACTCACTC
    4

    样例输出 2

    2

    样例解释 2

    对于这段 DNA 序列,连续的 444 个碱基组成的碱基序列为:ACTC, CTCA, TCACCACT。其中 ACTC 出现 222 次,其余均出现 111 次,所以出现最多的次数为 222,即为答案。

    数据范围与提示

    记 DNA 序列长度为 nnn。
    本题共 101010 组数据,只有输出与标准输出一致才可以获得该测试点的分数。

    下面给出每组数据的范围和满足性质情况:

    测试点编号nnnkkk其他
    111 =105=10 ^5=105​​ =1=1=1 满足性质
    2,32,32,3 ≤5×105le 5 imes 10 ^55×105​​ =1=1=1 -
    444 ≤5×105le 5 imes 10 ^55×105​​ ≤10le 1010 满足性质
    5,6,7,85,6,7,85,6,7,8 ≤106le 10 ^6106​​ ≤10le 1010 -
    9,109,109,10 =5×106=5 imes 10 ^6=5×106​​ =10=10=10 -

    性质:给出的 DNA 碱基序列中每个碱基均相同。
    对于所有数据均保证 k≤nkle nkn

    思路分析 : hash 拉链即可解决

    代码示例:

    using namespace std;
    #define ll unsigned long long
    const ll maxn = 5e6+5;
    const ll mm = 200007;
    
    char s[maxn];
    ll k, len;
    ll p = 19873;
    ll hash_[maxn], pp[maxn];
    
    void init_hash() {
        hash_[0] = 0; pp[0] = 1;
        for(ll i = 1; i <= len; i++) {
            hash_[i] = hash_[i-1]*p + (s[i]-'a'); 
            pp[i] = pp[i-1]*p;
        }  
    }
    struct node
    {
        ll x;
        ll cnt = 0;
        int next; //!!!
    }arr[maxn];
    int head[mm+50];
    ll tot = 1;
    
    ll _max(ll a, ll b){
        return a>b?a:b;
    }
    void solve() {
        ll ans = 1;
        memset(head, -1, sizeof(head));    
        for(ll i = k; i <= len; i++){
            ll num = hash_[i]-hash_[i-k]*pp[k];
            ll num2 = num%mm;
            int f = head[num2];
            int sign = 0;
            while(f != -1) {
                if (arr[f].x == num) {
                    arr[f].cnt++;
                    ans = _max(ans, arr[f].cnt);
                    sign = 1;
                    break;
                }
                f = arr[f].next;
            }
            if (sign) continue;
            arr[tot].x = num;
            arr[tot].cnt = 1;
            arr[tot].next = head[num2];
            head[num2] = tot++;
        }
        printf("%lld
    ", ans);
    }
    
    int main() {
        
        scanf("%s", s+1);
        len = strlen(s+1);
        scanf("%llu", &k);
        init_hash();
        solve();
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    JPA各种类型映射处理
    HTML URL编码
    C# 温故而知新:Stream篇(二)
    数据集
    C#可调用API接口来获取窗口句柄,代码如下:
    C# 温故而知新:Stream篇(三)
    SQL的主键和外键约束
    C# 温故而知新: 线程篇(三)
    C# 温故而知新:Stream篇(四)
    C# 温故而知新:Stream篇(—)
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9648246.html
Copyright © 2020-2023  润新知