码迷,mamicode.com
首页 > 其他好文 > 详细

GDKOI2014 基因模式

时间:2014-08-08 23:47:56      阅读:422      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   for   2014   

Description

bubuko.com,布布扣
 

Input

bubuko.com,布布扣

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

bubuko.com,布布扣

 

对于询问串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\n",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);
}

 

GDKOI2014 基因模式,布布扣,bubuko.com

GDKOI2014 基因模式

标签:des   style   blog   http   color   io   for   2014   

原文地址:http://www.cnblogs.com/applejxt/p/3900157.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!