您的位置:首页 > 其它

GDKOI2014 基因模式

2014-08-08 21:02 134 查看

3572. 【GDKOI2014】基因模式 (Standard IO)

Time Limits: 1000 ms Memory Limits: 262144 KB

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
=i;
while(c=getchar(),c>='A'&&c<='Z'){
s[++n]=c;
bel
=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
=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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: