TJOI2017DNA

  • P3763 [TJOI2017]DNA
  • 字符串匹配,字符集大小为\(4\),认为相差不超过\(3\)即合法。
  • 对每一种字符分开考虑不同产生的贡献。
  • 对于串\(S\),如果当前位置相同则\(S_i=1\),否则\(S_i=0\)
  • 对于串\(T\)则相反。
  • 这样就保证了如果\(S\)串是字符\(str\),但是\(T\)串不是,那么就会产生\(1\)的贡献。
  • 然后\(ntt\)即可,不开\(O2\)\(t\)成暴力,卡了好久。
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define R register int
#define ll long long
#define il inline 
using namespace std;
const int N=100001;
const int M=300001;
const int mod=998244353;
const int Gi=3;
int t,n,m,inv,f[M],g[M],h[M],er,ans,lim=1,rd[M];
char S[N],T[N];
int Qpow(R x,R y){
    R ans=1,bas=x;
    while(y){
        if(y&1)ans=1ll*ans*bas%mod;
        bas=1ll*bas*bas%mod,y>>=1;
    }return ans;
}
int gi(){
    R x=0,k=1;char c=getchar();
    while(c!='-'&&(c<'0'||c>'9'))c=getchar();
    if(c=='-')k=-1,c=getchar();
    while(c<='9'&&c>='0')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*k;
}
void ntt(R *A,R op){
    for(R i=0;i<lim;++i)if(i<rd[i])swap(A[i],A[rd[i]]);
    for(R mid=1;mid<lim;mid<<=1){
        R Wn=Qpow(Gi,(mod-1)/(mid<<1));
        if(op==-1)Wn=Qpow(Wn,mod-2);
        for(R len=mid<<1,j=0;j<lim;j+=len){
            R W=1;
            for(R k=0;k<mid;++k,W=1ll*W*Wn%mod){
                R x=A[j+k],y=1ll*W*A[j+k+mid]%mod;
                A[j+k]=(x+y)%mod,A[j+k+mid]=(x-y+mod)%mod;
            }
        }
    }
}
void Do(char p){
    for(R i=0;i<lim;++i)f[i]=g[i]=0;
    for(R i=0,j=n-1;i<n;++i,--j)f[j]=(S[i]==p);
    for(R i=0;i<m;++i)g[i]=(T[i]!=p);
    ntt(f,1),ntt(g,1);
    for(R i=0;i<lim;++i)f[i]=1ll*f[i]*g[i]%mod;
    ntt(f,-1);
    for(R i=0;i<lim;++i)h[i]=h[i]+1ll*f[i]*inv%mod;
}
void sol(){
    scanf("%s",T),scanf("%s",S);
    n=strlen(S),m=strlen(T),ans=er=0,lim=1;
    while(lim<n+m)er++,lim<<=1;
    for(R i=0;i<lim;++i)h[i]=0,rd[i]=(rd[i>>1]>>1)|((i&1)<<(er-1));
    if(!inv)inv=Qpow(lim,mod-2);
    Do('A'),Do('C'),Do('G'),Do('T');
    for(R i=n-1;i<m;++i)ans+=(h[i]<=3);
    printf("%d\n",ans);
}
int main(){
    t=gi();while(t--)sol();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Tyher/p/10051191.html