bzoj-2083 Intelligence test

来源:互联网 发布:金盛集团网络登录平台 编辑:程序博客网 时间:2024/06/01 08:34

题意:

给出一个长度为n的序列A,和m个序列Bi;

求每个Bi是否为A的子序列;

1<=n<=1000000,Bi总长度<=1000000;


题解:
这题听起来是sb题但是算法还是挺有趣。。

(给自己不会找个借口)

一个个判B串是否满足显然是T的,因为每次都要遍历A;

所以考虑仅遍历一次A串;

将所有B串存成链表的形式,插在Bi首字母的链表头里;

然后枚举A串,扫一遍当前的A[i],对所有B串去掉头(smg)之后放到下一个链表头里;

如果这时Bi为空则标记此串为TAK,否则为NIE;

时间复杂度为O(n+∑len(B));

这玩意感觉不太好调啊。。而且读入加不加优化简直两个世界[喷水];


代码:


#include<cctype>#include<stdio.h>#include<string.h>#include<algorithm>#define N 1100000#define LEN 1<<16using namespace std;int a[N],b[N];int val[N<<1],next[N<<1],_next[N<<1],head[N],tot;int ans[N];char getc(){    static char *S,*T,buf[LEN];    if(S==T)    {        T=(S=buf)+fread(buf,1,LEN,stdin);        if(S==T)            return EOF;    }    return *S++;}int read(){    static char ch;    static int D;    while(!isdigit(ch=getc()));    for(D=ch-'0';isdigit(ch=getc());)        D=D*10+ch-'0';    return D;}int main(){    int n,m,i,j,k,x,y;    n=read();    for(i=1;i<=n;i++)        a[i]=read();    m=read();    for(i=1;i<=m;i++)    {        k=read();        for(j=1;j<=k;j++)            val[tot+j]=read(),next[tot+j]=tot+j+1;        _next[tot+1]=head[val[tot+1]];        head[val[tot+1]]=tot+1;        val[tot+k+1]=i;        tot+=k+1;    }    for(i=1;i<=n;i++)    {        for(x=head[a[i]],head[a[i]]=0;x;x=_next[x])        {            if(!next[next[x]])            {                ans[val[next[x]]]=1;                continue;            }            _next[next[x]]=head[val[next[x]]];            head[val[next[x]]]=next[x];        }    }    for(i=1;i<=m;i++)        if(ans[i])            puts("TAK");        else            puts("NIE");    return 0;}



0 0
原创粉丝点击