BZOJ 4892 [Tjoi2017]dna 哈希+二分

自己简直是傻死了。。。对于位置想错了。。。


 

二分出来的是LCP长度$+1$,即每一次二分出来的最后一个点都是失配的,而就算失配也会跳过这个点;所以当$k<=3$且模式串$s2$的指针$>len2$时,即跳过了$<=3$个点的位置且指针$>len2$时,都是可行的;当$k==4$且模式串$s2$指针$>len2+1$时,即跳过了$<=4$个点的位置$>len2+1$时,是可行的。注意到时$len2+1$,原因是多失配了一个四号点。

然后一晚上又过去了$qwq$

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll unsigned long long
#define R register int
using namespace std;
namespace Fread {
    //static char B[1<<15],*S=B,*D=B;
    //#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
}using Fread::g;
const int N=100010,B=131;
ll h1[N],h2[N],p[N]; int n,l1,l2,t;
char s1[N],s2[N];
inline ll H1(int l,int r) {return h1[r]-h1[l-1]*p[r-l+1];}
inline ll H2(int l,int r) {return h2[r]-h2[l-1]*p[r-l+1];}
inline int ck(int x) {
    R i=x,j=1; R l=0,r=l2+1;
    for(R k=1;k<=4;++k) {
        while(l<r) { R md=l+r>>1; 
            if(H1(i,i+md-1)==H2(j,j+md-1)) l=md+1; else r=md;
        } i+=l,j+=l;
        l=0,r=l2-j+2;
        if(k==4) {if(j-2>=l2) return 1;}
        else if(j-1>=l2) return 1; 
    } return 0;
}
signed main() {
#ifdef JACK
    freopen("NOIPAK++.in","r",stdin);
#endif
    p[0]=1; for(R i=1;i<=N-10;++i) p[i]=p[i-1]*B;
    t=g(); while(t--) { R ans=0;
        scanf("%s%s",s1+1,s2+1); l1=strlen(s1+1),l2=strlen(s2+1);
        if(l1<l2) {printf("0\n"); continue;}
        for(R i=1;i<=l1;++i) h1[i]=h1[i-1]*B+s1[i];
        for(R i=1;i<=l2;++i) h2[i]=h2[i-1]*B+s2[i];
        for(R i=1;i<=l1-l2+1;++i) ans+=ck(i); printf("%d\n",ans);
    }
} 

2019.06.10\11

posted @ 2019-06-11 00:24  LuitaryiJack  阅读(208)  评论(0编辑  收藏  举报