zoukankan      html  css  js  c++  java
  • bzoj4892: [Tjoi2017]dna

    Description

    允许至多三个位置不同的字符串匹配

    枚举匹配起始位置,分治处理,用hash可以判定区间是否相等,若不相等则判断区间端点是否相等,找到至少4个不等的位置就return,否则递归到左右半部分处理

    类似于线段树,时间复杂度O(nlogn)

    #include<cstdio>
    #include<cstring>
    const int N=100007;
    typedef unsigned long long u64;
    const int p=1234577;
    int T,l1,l2,c;
    char s1[N],s2[N];
    u64 h1[N],h2[N],pp[N];
    void chk(int l1,int r1,int l2,int r2){
        while(c<=3&&l1<=r1){
            if(s1[l1]!=s2[l2])++l1,++l2,++c;
            else if(s1[r1]!=s2[r2])--r1,--r2,++c;
            else break;
        }
        if(c>3||l1>r1)return;
        if(h1[r1]-h2[r2]==(h1[l1-1]-h2[l2-1])*pp[r1-l1+1])return;
        int d=(r1-l1)>>1;
        chk(l1,l1+d,l2,l2+d);
        chk(l1+d+1,r1,l2+d+1,r2);
    }
    void work(){
        l1=strlen(s1+1);
        l2=strlen(s2+1);
        for(int i=1;i<=l1;++i)h1[i]=h1[i-1]*p+s1[i];
        for(int i=1;i<=l2;++i)h2[i]=h2[i-1]*p+s2[i];
        int ans=0;
        for(int i=1;i<=l1-l2+1;++i){
            c=0;
            chk(i,i+l2-1,1,l2);
            if(c<=3)++ans;
        }
        printf("%d
    ",ans);
    }
    int main(){
        for(int i=pp[0]=1;i<=100000;++i)pp[i]=pp[i-1]*p;
        for(scanf("%d",&T);T;--T){
            scanf("%s%s",s1+1,s2+1);
            work();
        }
        return 0;
    }
  • 相关阅读:
    最简单的UDP程序
    最简单的TCP程序
    一道面试题的分析
    JDK5新特性:可变参数方法
    文件IO流总结
    集合使用的总结
    双列集合Map的嵌套遍历
    集合HashSet的使用
    集合TreeSet的使用
    用LinkedList模拟Stack功能
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6811958.html
Copyright © 2011-2022 走看看