[JZOJ4370] hypocritical

2023-11-09 14:20
文章标签 hypocritical jzoj4370

本文主要是介绍[JZOJ4370] hypocritical,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

这里写图片描述
这里写图片描述

Solution

几乎没有什么思维难度

先将原树建成一个Trie,此时Trie上的节点已经合并了一些终点了,合并的时候DP背包一下

然后再BFS把Trie建成SAM,那么就变成了在Fail树上DP,子树选取,直接背包即可

代码略为猥琐

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#define mo 998244353
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 300005
#define LL long long
using namespace std;
int t[N][6],t1[N][6],n,m1,m,num,n1,n2,fail[N],mx[N],vl[N],d[N],nt[2*N],dt[2*N],fs[N],dv[N],pt[N],dc[N];
LL f[N][17],pr[N],g[N][17],s[N][17];
bool bz[N];
void link(int x,int y)
{
    nt[++m1]=fs[x];
    dt[fs[x]=m1]=y;
}
void dfs(int k,int ft,int q)
{
    int c=vl[k];
    if(!t1[q][c]) t1[q][c]=++n1;
    q=t1[q][c];
    f[q][0]=1;
    fod(j,16,1) f[q][j]=(f[q][j]+f[q][j-1]*pr[k])%mo;
    for(int i=fs[k];i;i=nt[i]) if(dt[i]!=ft) dfs(dt[i],k,q);
}
void bfs()
{
    int l=0,r=0;
    n2=1;
    fo(i,0,num-1)
    {
        if(!bz[t1[1][i]]&&t1[1][i]) 
        {
            bz[t1[1][i]]=1;
            d[++r]=t1[1][i];
            dc[r]=i;
            dv[t1[1][i]]=1;
        }
    }
    while(l<r)
    {
        int k=d[++l],p=dv[k],c=dc[l],ls=++n2;
        mx[ls]=mx[p]+1,pt[ls]=k;
        fo(i,0,16) g[ls][i]=f[k][i];
        while(p&&!t[p][c]) t[p][c]=ls,p=fail[p];
        if(p)
        {
            int q=t[p][c];
            if(mx[q]==mx[p]+1) fail[ls]=q;
            else
            {
                fail[++n2]=fail[q];
                fail[q]=fail[ls]=n2;
                mx[n2]=mx[p]+1;
                fo(i,0,num-1) t[n2][i]=t[q][i];
                while(p&&t[p][c]==q) t[p][c]=n2,p=fail[p];
            }
        }
        else fail[ls]=1;
        fo(i,0,num-1)
        {
            if(!bz[t1[k][i]]&&t1[k][i]) 
            {
                bz[t1[k][i]]=1;
                d[++r]=t1[k][i];
                dc[r]=i;
                dv[t1[k][i]]=ls;
            }
        }
    }
}
void dp(int k)
{
    g[k][0]=1;
    for(int i=fs[k];i;i=nt[i])
    {
        int p=dt[i];
        dp(p);
        if(k>1)
        fod(j,16,1) 
            fo(q,1,j) g[k][j]=(g[k][j]+g[p][q]*g[k][j-q])%mo;
    }
    if(k>1) fo(j,1,16) s[mx[fail[k]]+1][j]+=g[k][j],s[mx[k]+1][j]-=g[k][j];
}
int main()
{
    cin>>n>>m>>num;
    scanf("\n");
    fo(i,1,n)
    {
        char ch=getchar();
        vl[i]=ch-'a';
    }
    fo(i,1,n) scanf("%lld",&pr[i]);
    fo(i,1,n-1)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        link(x,y),link(y,x);
    }
    n1=n2=1;
    dfs(1,0,1);
    bfs();
    memset(fs,0,sizeof(fs));
    memset(nt,0,sizeof(nt));
    m1=0;
    fo(i,2,n2) link(fail[i],i);
    dp(1);
    fo(i,1,2*n)
        fo(j,1,16) s[i][j]=(s[i][j]+s[i-1][j])%mo;
    fo(i,1,m)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%lld\n",(s[x][y]+mo)%mo);
    }
}   

这篇关于[JZOJ4370] hypocritical的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/376629

相关文章

【NOI2016模拟3.1】hypocritical

Description Input Output 第i行一个整数表示第i个询问的答案 Sample Input 6 3 3 aaabbb 2 3 2 5 7 10 1 2 1 3 2 4 2 5 3 6 1 3 2 2 3 1 Sample Output 362 161 22 Data Constraint n<=100000,s<=5,t<=16