zoukankan      html  css  js  c++  java
  • GDKOI2014 基因模式

    Description

     

    Input

    Output

    对于每个询问,输出一行,表示对应的询问中符合要求的子串数目。

    注意两个子串在S中位于不同位置即视为不同子串,即使它们对应的序列相同。

    空串不计算在内。
     

    Sample Input

    输入1:

    3

    GATATG

    ATA

    a

    GATAT

    a

    GATATG

    aT

    输入2:

    2

    ACTG

    ACTGACTG

    A

    ACTGACTG

    a

    Sample Output

    输出1:

    2

    7

    5

    输出2:

    8

    12
     

    Data Constraint

    对于询问串S,定义near[i]为以第i位为起点同时为T的子串的最长串的长度,则Si-i+near[i]-1串的任一子串都为T的子串

    求解near的过程用SA和rmq实现

    然后用一个二进制数表示对各个字母的奇偶性要求。f[i]表示以满足奇偶性为i的字符串数

    对于第i位,为S子串的起点和终点为i和i+near[i]-1,这两个值都单调不下降。

    对于末尾的转移,设x为后一位字母用二进制表示的奇偶性,f[i]=f'[i^x],且f[x]=f[x]+1(表示增加这一位的单个字符串)

    对于首的转移,在对应位减一即可

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    
    int i,t,n,mj,ext,mn,x,len,j;
    int sa[300011],rank[300011],h[300011],co[300011],nr[300011];
    int a[300011],b[300011],near[300011],f[3][30],bel[300011],ans[1011];
    int lef[300011],rig[300011];
    char s[300011],s1[1011];
    bool p[1011][5];
    struct tree{
        int x,z,q;
    }tr[1200011];
    
    void Read()
    {
        char c;
        while(c=getchar(),c<'A'||c>'Z');
        s[++n]=c;
        bel[n]=i;
        while(c=getchar(),c>='A'&&c<='Z'){
            s[++n]=c;
            bel[n]=i;
        }
    }
    
    void sort(int *a)
    {
        int i;
        for(i=0;i<=mn;i++)co[i]=0;
        for(i=1;i<=n;i++)co[a[i]+1]++;
        for(i=1;i<=mn;i++)co[i]+=co[i-1];
        for(i=1;i<=n;i++)nr[i]=0;
        for(i=1;i<=n;i++){
            co[a[sa[i]]]++;
            nr[co[a[sa[i]]]]=sa[i];
        }
        for(i=1;i<=n;i++)sa[i]=nr[i];
    }
    
    void getrank()
    {
        int i;
        x=0;
        for(i=1;i<=n;i++){
            if(i==1||a[sa[i]]!=a[sa[i-1]]||b[sa[i]]!=b[sa[i-1]])x++;
            rank[sa[i]]=x;
        }
        mn=x;
    }
    
    void Suffix()
    {
        int i,j,k,l,last;
        for(i=1;i<=n;i++){
            if(s[i]!='#')a[i]=s[i]-64;
            b[i]=0;
            sa[i]=i;
        }
        sort(a);
        getrank();
        l=1;
        while(x!=n){
            for(i=1;i<=n;i++){
                a[i]=rank[i];
                if(i+l<=n)b[i]=rank[i+l];
                else b[i]=0;
            }
            sort(b);
            sort(a);
            getrank();
            l*=2;
        }
        last=0;
        for(i=1;i<=n;i++){
            if(last)last--;
            if(rank[i]==1)continue;
            j=i;
            k=sa[rank[i]-1];
            while(j+last<=n&&k+last<=n&&s[j+last]==s[k+last]&&s[j+last]!='#')last++;
            h[rank[i]]=last;
        }
    }
    
    void build(int l,int r,int t)
    {
        int mid;
        if(l==r){
            tr[t].x=l;
            tr[t].z=r;
            tr[t].q=h[l];
            return;
        }
        tr[t].x=l;
        tr[t].z=r;
        mid=(l+r)/2;
        build(l,mid,t+t);
        build(mid+1,r,t+t+1);
        tr[t].q=min(tr[t+t].q,tr[t+t+1].q);
    }
    
    int ask(int l,int r,int t)
    {
        int mid;
        if(l==tr[t].x&&r==tr[t].z)return tr[t].q;
        mid=(tr[t].x+tr[t].z)/2;
        if(r<=mid)return ask(l,r,t+t);
        if(l>mid)return ask(l,r,t+t+1);
        if(l<=mid&&r>mid)return min(ask(l,mid,t+t),ask(mid+1,r,t+t+1));
    }
    
    void Work(int x)
    {
        int i,j,k,l,rn,xzq,ap,ple,z,q,xz,r,e;
        bool pp;
        xzq=0;
        for(i=mj;i<=n;i++){
            if(bel[i]!=x)break;
            rn=i-mj+1;
            l=lef[rank[i]];
            r=rig[rank[i]];
            if(l!=0){
                if(l<rank[i])ap=ask(l+1,rank[i],1);
                else ap=ask(rank[i]+1,l,1);
            }
            if(r!=0){
                if(r<rank[i])ple=ask(r+1,rank[i],1);
                else ple=ask(rank[i]+1,r,1);
            }
            if(ap>ple)near[rn]=ap;
            else near[rn]=ple;
        }
        for(i=0;i<=15;i++){
            f[0][i]=0;
            f[1][i]=0;
        }
        z=0;
        l=1;
        for(i=mj;i<=n;i++){
            if(bel[i]!=x)break;
            rn=i-mj+1;
            if(rn!=1){
                f[1-l][z]--;
                if(s[i-1]=='A')z^=1;
                if(s[i-1]=='G')z^=2;
                if(s[i-1]=='C')z^=4;
                if(s[i-1]=='T')z^=8;
            }
            for(j=rn-1+near[rn-1];j<rn+near[rn];j++)if(j!=0){
                if(s[j+mj-1]=='A')xz=1;
                if(s[j+mj-1]=='G')xz=2;
                if(s[j+mj-1]=='C')xz=4;
                if(s[j+mj-1]=='T')xz=8;
                z^=xz;
                for(k=0;k<=15;k++)f[l][k]=f[1-l][k^xz];
                f[l][xz]++;
                for(k=0;k<=15;k++){
                    pp=true;
                    if(p[x][1]==false){
                        q=k&1;
                        e=ans[x]&1;
                        if(q!=e)pp=false;
                    }
                    if(p[x][2]==false){
                        q=k&2;
                        e=ans[x]&2;
                        if(q!=e)pp=false;
                    }
                    if(p[x][3]==false){
                        q=k&4;
                        e=ans[x]&4;
                        if(q!=e)pp=false;
                    }
                    if(p[x][4]==false){
                        q=k&8;
                        e=ans[x]&8;
                        if(q!=e)pp=false;
                    }
                    if(pp)xzq+=f[l][k];
                }
                l=1-l;
            }
        }
        mj=i+1;
        printf("%d
    ",xzq);
    }
    
    int main()
    {
        memset(p,true,sizeof(p));
        scanf("%d",&t);
        i=0;
        Read();
        mj=n+2;
        ext=27;
        for(i=1;i<=t;i++){
            s[++n]='#';
            a[n]=ext++;
            Read();
            scanf("%s",&s1);
            len=strlen(s1);
            for(j=0;j<len;j++){
                if(s1[j]=='A')ans[i]^=1;
                if(s1[j]=='G')ans[i]^=2;
                if(s1[j]=='C')ans[i]^=4;
                if(s1[j]=='T')ans[i]^=8;
                if(s1[j]=='A'||s1[j]=='a')p[i][1]=false;
                if(s1[j]=='G'||s1[j]=='g')p[i][2]=false;
                if(s1[j]=='C'||s1[j]=='c')p[i][3]=false;
                if(s1[j]=='T'||s1[j]=='t')p[i][4]=false;
            }
        }
        mn=ext;
        Suffix();
        lef[0]=0;
        for(i=1;i<=n;i++){
            if(bel[sa[i]]==0)lef[i]=i;
            else lef[i]=lef[i-1];
        }
        rig[n+1]=0;
        for(i=n;i>=1;i--){
            if(bel[sa[i]]==0)rig[i]=i;
            else rig[i]=rig[i+1];
        }
        build(1,n,1);
        for(i=1;i<=t;i++)Work(i);
    }
  • 相关阅读:
    FFTW3学习笔记2:FFTW(快速傅里叶变换)中文参考
    小程序中用rich-text来实现ul功能 (代码)
    微信小程序中如何实现列表渲染多层嵌套循环
    小程序中实现选择预览图片同时可以实现长按删除图片的代码
    微信小程序实例:获取当前城市位置及再次授权地理位置的代码实现
    微信小程序实例:实现顶部tab切换以及滑动切换时导航栏会随着移动的效果(代码)
    入门微信小程序直播
    微信小程序之登录态
    微信小程序之本地缓存
    微信小程序之页面路由
  • 原文地址:https://www.cnblogs.com/applejxt/p/3900157.html
Copyright © 2011-2022 走看看