[HNOI2019]JOJO

https://www.luogu.org/problemnew/show/P5287

题解

可持久化\(KMP\)

那个退回操作我们可以把它看做在操作树上\(dfs\),所以我们可以先把这个树弄出来。

对于连续一段串的匹配问题。

我们可以搞个\(KMP\)自动机,输入当前节点编号也就是\(nxt\),输入下一段连续的字符串,输出\(nxt\)跳完之后的值。

然后我们可以把这个字符串的\(fail\)树弄出来,然后把它搞成一个主席树,相当于是我们令\(ch[now][c][len]\)为这个自动机,第三维比较大,用线段树维护,然后\(dfs\)这颗操作树的时候顺便维护这个节点的\(nxt\),这个点的主席树从fail节点继承。

还要维护从这个点到\(fail\)树根的一条链上\(x\)字符的最长长度,还要在线段树上维护匹配时产生的贡献。

注意特判一些情况比如说开头结尾的字符时一样的。

代码

#include
#define mm make_pair
#define P pair
#define ls tr[cnt].l
#define rs tr[cnt].r
#define N 100009
using namespace std;
typedef long long ll;
const int M=10001;
vectorvec[N];
const int mod=998244353;
int tot,head[N],rt[N][26],mx[N][26],pos[N],tag,top,n,tott,len[N];
P rec[N];
ll ans[N];
inline ll rd(){
  ll x=0;char c=getchar();bool f=0;
  while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  return f?-x:x;
}
struct node{
  int l,r,nxt;
  ll sum,la;
}tr[N*30];
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline int newnode(int pre){
  ++tott;
  tr[tott]=tr[pre];
  return tott;
}
inline void pushdown(int cnt,int l1,int l2){
   ls=newnode(ls);
   MOD(tr[ls].sum=l1*tr[cnt].la%mod);
   rs=newnode(rs);
   MOD(tr[rs].sum=l2*tr[cnt].la%mod);
   tr[ls].la=tr[rs].la=tr[cnt].la;
   tr[cnt].la=0;
}
void query(int cnt,int l,int r,int R,ll &ans,int &nxt){
  if(r>1;
  if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
  query(ls,l,mid,R,ans,nxt);
  if(mid>1;
    if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
    upd(ls,l,mid,R,x,nxt);
    if(mid::iterator it=vec[u].begin();it!=vec[u].end();++it){
    int v=*it;
    ans[v]=ans[u];
    memcpy(mx[top+1],mx[nxt+1],sizeof(mx[top+1]));
    memcpy(rt[top+1],rt[nxt+1],sizeof(rt[top+1]));
    dfs(v);
  }
  --top;
}
int main(){
  n=rd();
  int opt,x;
  for(int i=1;i<=n;++i){
    opt=rd();x=rd();
    if(opt==1){
      char c;
      cin>>c;
      rec[++tot]=mm(c-'a',x);
      pos[i]=tot;
      vec[pos[i-1]].push_back(pos[i]);   
    }
    else{
      pos[i]=pos[x];
    }
  }
  for(vector::iterator it=vec[0].begin();it!=vec[0].end();++it){
    int v=*it;
    tott=0;
    memset(rt[1],0,sizeof(rt[1]));
    memset(mx[1],0,sizeof(mx[1]));
    dfs(v);
  }
  for(int i=1;i<=n;++i)printf("%d\n",ans[pos[i]]);
  return 0;
}

转载于:https://www.cnblogs.com/ZH-comld/p/10940485.html

你可能感兴趣的:([HNOI2019]JOJO)