• [TJOI2017] DNA


    [TJOI2017] DNA

    Description

    求模式串与主串的匹配次数,容错不超过三个字符。

    Solution

    枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功。考虑到容错量很小,所以每个位置开始的匹配过程中大部分与普通匹配是同样操作,而我们需要的其实就是 LCP 长度,所以预处理出后缀数组和高度数组,建 ST 表支持 RMQ 询问,来加速暴力匹配的过程。时间复杂度 (O(n log n))

    #include <bits/stdc++.h>
    using namespace std;
    
    int n,k,l0,m=256,sa[250005],y[250005],u[250005],v[250005],o[250005],r[250005],h[250005],T;
    char str[250005];
    int lg2[250005];
    
    struct clsst {
        int a[250005][21];
        void build(int *src,int n) {
            for(int i=1;i<=n;i++) a[i][0]=src[i];
            for(int i=1;i<=20;i++)
                for(int j=1;j<=n-(1<<i)+1;j++)
                    a[j][i]=min(a[j][i-1],a[j+(1<<(i-1))][i-1]);
        }
        int query(int l,int r) {
            if(l>r) swap(l,r);
            int j=lg2[r-l+1];
            return min(a[l][j],a[r-(1<<j)+1][j]);
        }
    } st;
    
    int lcp(clsst *st,int p,int q)
    {
        if(r[p]>r[q]) swap(p,q);
        return st->query(r[p]+1,r[q]);
    }
    
    int match(clsst *st,int p,int q)
    {
        return lcp(st,p,l0+1+q);
    }
    
    int matchstr(clsst *st,int p,int q,int x)
    {
        if(x<0) return 0;
        if(q>k-x) return 1;
        int step = match(st,p,q);
        //cout<<"matchstr "<<p<<" "<<q<<" "<<x<<" "<<step<<endl;
        p+=step-1;
        q+=step-1;
        if(q>=k-x) return 1;
        else return matchstr(st,p+2,q+2,x-1);
    }
    
    int main(){
    	for(int i=1;i<=250000;i++) lg2[i]=log2(i);
    
    	scanf("%d",&T);
    
    	while(T--) {
    		memset(sa,0,sizeof sa);
    		memset(y,0,sizeof y);
    		memset(u,0,sizeof u);
    		memset(v,0,sizeof v);
    		memset(o,0,sizeof o);
    		memset(r,0,sizeof r);
    		memset(h,0,sizeof h);
    		memset(str,0,sizeof str);
    
    		scanf("%s",str+1);
    		n=l0=strlen(str+1);
    
    		str[n+1]='$';
    
    		scanf("%s",str+n+2);
    		k=strlen(str+n+2);
    		n+=k+1;
    
    		for(int i=1;i<=n;i++) u[str[i]]++;
    		for(int i=1;i<=m;i++) u[i]+=u[i-1];
    		for(int i=n;i>=1;i--) sa[u[str[i]]--]=i;
    		r[sa[1]]=1;
    		for(int i=2;i<=n;i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
    
    		for(int l=1;r[sa[n]]<n;l<<=1) {
    			memset(u,0,sizeof u);
    			memset(v,0,sizeof v);
    			memcpy(o,r,sizeof r);
    			for(int i=1;i<=n;i++) u[r[i]]++, v[r[i+l]]++;
    			for(int i=1;i<=n;i++) u[i]+=u[i-1], v[i]+=v[i-1];
    			for(int i=n;i>=1;i--) y[v[r[i+l]]--]=i;
    			for(int i=n;i>=1;i--) sa[u[r[y[i]]]--]=y[i];
    			r[sa[1]]=1;
    			for(int i=2;i<=n;i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
    		}
    		{
    			int i,j,k=0;
    			for(int i=1;i<=n;h[r[i++]]=k)
    				for(k?k--:0,j=sa[r[i]-1];str[i+k]==str[j+k];k++);
    		}
            memset(st.a,0,sizeof st.a);
    		st.build(h,n);
            int ans = 0;
    		for(int i=1;i<=l0-k+1;i++)
            {
                //cout<<"try "<<i<<endl;
                int tmp = matchstr(&st,i,1,3);
                //if(tmp==1) cout<<i<<endl;
                ans += tmp;
            }
            cout<<ans<<endl;
    	}
    }
    
  • 相关阅读:
    软件工程第四次作业
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    软件工程最后一次作业
    软件工程第四次作业
    软件工程第二次作业
    软件工程最后一次作业
    软件工程第二次结对作业
    软件工程第三次作业
  • 原文地址:https://www.cnblogs.com/mollnn/p/11770758.html
Copyright © 2020-2023  润新知