【题解】SP8093 JZPGYZ - Sevenk Love Oimaster

SP8093 JZPGYZ - Sevenk Love Oimaster

\(\text{Solution:}\)

坑人的 spoj 不给数据)傻逼的笔者做到了 CF204E Little Elephant and Strings 才仔细想明白自己为啥子树数颜色错了好久……

显然,建立好广义 SAM 并且给属于不同串的节点染色之后,就变成了一个 parent 树上的子树数颜色问题。

那这个问题长得很 HH的项链 啊。考虑把每一个点的子树都求出来,设 \(cpos[i]\) 表示颜色 \(i\) 上此出现的 dfs序 是什么。

由于我们根据 dfs序 把原问题转化到的序列上,所以我们也要保证做的时候 dfs序 单调,而不是点编号。

然后就是一个简单的数颜色啦:对当前 dfs序,单点 \(+1\) 并且把上一次出现位置 \(-1...\) 但愉快写完后发现自己 WA 了,还不能看数据也不知道答案偏大偏小。

那问题就很玄学了,死活不知道哪里写错。实际上:你颜色都是非负的,但这样处理会把没有颜色的节点当成一种颜色,答案就错了。

剩下就没啥问题了 一个树状数组的事情罢了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
inline int lowbit(int x){return x&(-x);}
int tr[N];
namespace SAM{
    int len[N],pa[N],ch[N][26],tag[N];
    int last=1,tot=1,dfn[N],dfstime;
    int pos[N],cpos[N],siz[N],num[N];
    int rk[N],colf[N];
    vector<int>G[N],qr[N];
    void insert(const int &c,const int &col){
        int p=last;
        int np=++tot;
        last=tot;len[np]=len[p]+1;tag[np]=col;
        for(;p&&!ch[p][c];p=pa[p])ch[p][c]=np;
        if(!p)pa[np]=1;
        else{
            int q=ch[p][c];
            if(len[q]==len[p]+1)pa[np]=q;
            else{
                int nq=++tot;
                len[nq]=len[p]+1;
                memcpy(ch[nq],ch[q],sizeof ch[q]);
                pa[nq]=pa[q];pa[q]=pa[np]=nq;
                for(;p&&ch[p][c]==q;p=pa[p])ch[p][c]=nq;
            }
        }
    }
    void dfs(int x){
        dfn[x]=++dfstime;siz[x]=1;rk[dfstime]=x;
        colf[dfstime]=tag[x];
        for(auto i:G[x])dfs(i),siz[x]+=siz[i];
    }
    void change(int x,int v){
        while(x<=tot)tr[x]+=v,x+=lowbit(x);
    }
    int query(int x){
        int res=0;
        while(x)res+=tr[x],x-=lowbit(x);
        return res;
    }
    void BuildTree(){
        for(int i=2;i<=tot;++i)G[pa[i]].push_back(i);
        dfs(1);
        for(int i=1;i<=tot;++i)qr[dfn[i]+siz[i]-1].push_back(i);
        for(int i=1;i<=tot;++i){
            if(!cpos[colf[i]])cpos[colf[i]]=i;
            pos[i]=cpos[colf[i]];cpos[colf[i]]=i;
        }
        for(int i=1;i<=tot;++i){
        	if(!colf[i])continue;
            change(i,1);
            if(i!=pos[i])change(pos[i],-1);
            for(auto v:qr[i]){
                // printf("(%d %d)\n",i,dfn[v]);
                num[v]=query(i)-query(dfn[v]-1);
                // puts("?");
            }
        }
    }
}
using namespace SAM;
int n,m;
char s[N];
signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;++i){
        scanf("%s",s+1);
        last=1;
        int len=strlen(s+1);
        for(int j=1;j<=len;++j)insert(s[j]-'a',i);
    }
    BuildTree();
    // for(int i=1;i<=tot;++i)cout<<num[i]<<endl;
    for(int i=1;i<=m;++i){
        scanf("%s",s+1);
        int len=strlen(s+1);
        int node=1,fg=0;
        for(int j=1;j<=len&&!fg;++j){
            int v=s[j]-'a';
            if(ch[node][v])node=ch[node][v];
            else{puts("0");fg=1;break;}
        }
        if(!fg)printf("%lld\n",num[node]);
    }
    return 0;
}
posted @ 2021-08-23 16:24  Refined_heart  阅读(46)  评论(0编辑  收藏  举报