[SCOI2012]喵星球上的点名

题目描述

a180285 幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。

假设课堂上有 N 个喵星人,每个喵星人的名字由姓和名构成。喵星球上的老师会选择M 个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。

然而,由于喵星人的字码过于古怪,以至于不能用 ASCII 码来表示。为了方便描述,a180285 决定用数串来表示喵星人的名字。

现在你能帮助 a180285 统计每次点名的时候有多少喵星人答到,以及 M 次点名结束后每个喵星人答到多少次吗?

输入输出格式

输入格式:

现在定义喵星球上的字符串给定方法:

先给出一个正整数 L ,表示字符串的长度,接下来L个整数表示字符串的每个字符。

输入的第一行是两个整数 N 和 M。

接下来有 N 行, 每行包含第 i 个喵星人的姓和名两个串。 姓和名都是标准的喵星球上的字符串。

接下来有 M 行,每行包含一个喵星球上的字符串,表示老师点名的串。

输出格式:

对于每个老师点名的串输出有多少个喵星人应该答到。

然后在最后一行输出每个喵星人被点到多少次。

 ~~~~~~~~~~~~~~~~~~

某谷恶意加强数据。

首先吐槽卡trie图。字符集太大了,trie图会T得很厉害,建个图就超时了。

别人用map,然而我不喜欢迭代器,就用了treap维护儿子。

代码:

#include<ctime>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define N 200050
#define M 200050
inline int rd()
{
    int f=1,c=0;char ch = getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=(c<<3)+(c<<1)+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,tot;
int ls[M<<1],rs[M<<1],rnd[M<<1],w[M<<1];
struct Treap
{
    int rt;
    void lturn(int &x)
    {
        int y = rs[x];
        rs[x]=ls[y],ls[y]=x;
        x=y;
    }
    void rturn(int &x)
    {
        int y = ls[x];
        ls[x]=rs[y],rs[y]=x;
        x=y;
    }
    int query(int k,int x)
    {
        if(w[k]==x)return k;
        if(!k)return 0;
        return query(w[k]<x?rs[k]:ls[k],x);
    }
    void insert(int &k,int x)
    {
        if(!k)
        {
            k=++tot;
            rnd[k]=rand();
            w[k]=x;
            return ;
        }else if(w[k]<x)
        {
            insert(rs[k],x);
            if(rnd[rs[k]]<rnd[k])lturn(k);
        }else
        {
            insert(ls[k],x);
            if(rnd[ls[k]]<rnd[k])rturn(k);
        }
    }
};
int lin[M],sum;
struct nam
{
    int len1,len2;
    int l1,r1,l2,r2;
}q[N];
int hed[M<<1],cntt;
struct Trie
{
    Treap ch;
//    vector<int>vv;
    int f,ct;
}tr[M<<1];
struct EG
{
    int to,nxt;
}e[M];
void ae(int f,int t)
{
    e[++cntt].to = t;
    e[cntt].nxt = hed[f];
    hed[f] = cntt;
}
bool vis1[M],vis2[M];
void init()
{
    for(int i=1;i<=tot;i++)
        vis1[i]=0;
    for(int i=1;i<=n;i++)
        vis2[i]=0;
}
void acmach()
{
    queue<int>q,c;
    q.push(0);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        if(!tr[u].ch.rt)continue;
        c.push(tr[u].ch.rt);
        while(!c.empty())
        {
            int v = c.front();
            c.pop();
            if(ls[v])c.push(ls[v]);
            if(rs[v])c.push(rs[v]);
            int to = tr[u].f;
            while(to&&!tr[to].ch.query(tr[to].ch.rt,w[v]))to=tr[to].f;
            int hhh=tr[to].ch.query(tr[to].ch.rt,w[v]);
            if(hhh&&u)to=hhh;
            tr[v].f = to;
            q.push(v);
        }
    }
}
int as1[N],as2[M];
int deal(int u)
{
    int ret = 0;
    while(!vis1[u])
    {
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int i = e[j].to;
            vis2[i]=1;
            as2[i]++;
        }
        ret+=tr[u].ct;
        vis1[u]=1;
        u = tr[u].f;
    }
    return ret;
}
int main()
{
    srand(time(NULL));
    n=rd(),m=rd();
    int u,c,v;
    for(int i=1;i<=n;i++)
    {
        q[i].len1=rd();
        q[i].l1 = sum+1,q[i].r1 = sum+q[i].len1;
        for(int j=q[i].l1;j<=q[i].r1;j++)lin[j]=rd();
        sum+=q[i].len1;
        q[i].len2=rd();
        q[i].l2 = sum+1,q[i].r2 = sum+q[i].len2;
        for(int j=q[i].l2;j<=q[i].r2;j++)lin[j]=rd();
        sum+=q[i].len2;
    }
    for(int i=1;i<=m;i++)
    {
        c=rd();
        u=0;
        for(int j=1;j<=c;j++)
        {
            v=rd();
            if(!tr[u].ch.query(tr[u].ch.rt,v))tr[u].ch.insert(tr[u].ch.rt,v);
            u = tr[u].ch.query(tr[u].ch.rt,v);
        }
//        tr[u].vv.push_back(i);
        ae(u,i);
        tr[u].ct++;
    }
    acmach();
    vis1[0]=1;
    for(int i=1;i<=n;i++)
    {
        init();
        u=0;
        for(int j=q[i].l1;j<=q[i].r1;j++)
        {
            c = lin[j];
            while(u&&!tr[u].ch.query(tr[u].ch.rt,c))u=tr[u].f;
            int hhh = tr[u].ch.query(tr[u].ch.rt,c);
            if(hhh)u=hhh;
            as1[i]+=deal(u);
        }
        u=0;
        for(int j=q[i].l2;j<=q[i].r2;j++)
        {
            c = lin[j];
            while(u&&!tr[u].ch.query(tr[u].ch.rt,c))u=tr[u].f;
            int hhh = tr[u].ch.query(tr[u].ch.rt,c);
            if(hhh)u=hhh;
            as1[i]+=deal(u);
        }
    }
    for(int i=1;i<=m;i++)printf("%d\n",as2[i]);
    for(int i=1;i<=n;i++)printf("%d ",as1[i]);
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/9689720.html