zoukankan      html  css  js  c++  java
  • [TJOI2017] DNA 解题报告 (hash+二分)

    题目链接:https://www.luogu.org/problemnew/show/P3763

    题目大意:

    给定原串S0,询问S0有多少个子串和给定串S相差不到3个字母

    题解:

    我们枚举S0的子串,问题转化为如何高效的判断两个串是否相差不到三个字母

    考虑到数据范围,发现只能有log的时间余地

    自然想到二分

    solve每次找到第一个不同的位置并且返回,连续solve 4次,若S在这期间被处理完了,那么说明两个串相差不到3个字母

    当然还有一些小细节

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    typedef unsigned long long ull;
    const int N=1e5+15; 
    int lena,lenb;
    ull pin[N],haa[N],hab[N];
    char a[N],b[N];
    void H()
    {
        haa[0]=hab[0]=0;
        for (int i=1;i<=lena;i++)
        {
            haa[i]=haa[i-1]*113+a[i]-'a';
        }
        for (int i=1;i<=lenb;i++)
        {
            hab[i]=hab[i-1]*113+b[i]-'a';
        }
    }
    int solve(int x,int y)
    {
        int l=1,r=lenb;
        while (l<r)
        {
            int mid=l+r>>1;
            if ((haa[x+mid-1]-haa[x-1]*pin[mid])==(hab[y+mid-1]-hab[y-1]*pin[mid]))
            {
                l=mid+1;
            }
            else r=mid;
        }
        if (haa[x+l-1]-haa[x-1]*pin[l]!=hab[y+l-1]-hab[y-1]*pin[l])
        {
            return l;
        }
        else return l+1;
    }
    int check(int x)
    {
        int now=1,k; 
        for (int i=1;i<=3;i++)
        {
            k=solve(x,now);
            //printf("%d %d %d
    ",x,now,k);
            x+=k;now+=k;
            if (now>lenb) return 1;
        }
        k=solve(x,now);
        x+=k-2;now+=k-2;
        if (now>=lenb) return 1;
        return 0;
    }
    int main()
    {
        pin[0]=1;
        for (int i=1;i<=N;i++) pin[i]=pin[i-1]*113;
        int T;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%s",a+1);
            scanf("%s",b+1);
            lena=strlen(a+1),lenb=strlen(b+1);
            H();
            //printf("%d
    ",solve(2,3));
            int re=0;
            for (int i=1;i<=lena-lenb+1;i++)
            {
                if (check(i)) re++;
            }
            printf("%d
    ",re);
        }
        return 0;
    }
  • 相关阅读:
    隔离级别 && SNAPSHOT
    多态性&& 虚函数 && 抽象类
    socket编程
    [APIO2015]巴邻旁之桥
    LuoguP3701 「伪模板」主席树
    线段树标记永久化
    [HNOI2015]开店
    NOIP2017划水记
    FFTNTT总结
    [THUWC 2017]在美妙的数学王国中畅游
  • 原文地址:https://www.cnblogs.com/xxzh/p/9691942.html
Copyright © 2011-2022 走看看