p5341 [TJOI2019]甲苯先生和大中锋的字符串

Posted yzxverygood

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了p5341 [TJOI2019]甲苯先生和大中锋的字符串相关的知识,希望对你有一定的参考价值。

分析

TJOI白给题

建出sam,对于每个点如果它的子树siz和等于k

那么对于这个满足的点它有贡献的长度一定是一个连续区间

直接差分即可

代码

#include<bits/stdc++.h>
using namespace std;
int n,k,mx,ans,d[100100];
char s[100100];
struct SAM {
    int mp[200100][30],fa[200100],ed,ccnt,len[200100],siz[200100];
    int head[200100],nxt[200100],to[200100],cnt;
    inline void init(){
      mx=0;
      cnt=ans=0;
      ccnt=ed=1;
      memset(d,0,sizeof(d));
      memset(mp,0,sizeof(mp));
      memset(fa,0,sizeof(fa));
      memset(to,0,sizeof(to));
      memset(len,0,sizeof(len));
      memset(siz,0,sizeof(siz));
      memset(nxt,0,sizeof(nxt));
      memset(head,0,sizeof(head));
    }
    inline void add(int x,int y){
      nxt[++cnt]=head[x];
      head[x]=cnt;
      to[cnt]=y;
    }
    inline void ins(int x,int n1){
        int p=ed;
        ed=++ccnt;
        siz[ccnt]=1;
        len[ccnt]=n1;
        while(p&&!mp[p][x]){
          mp[p][x]=ed;
          p=fa[p];
        }
        if(!p){
          fa[ed]=1;
          return;
        }
        int q=mp[p][x];
        if(len[q]==len[p]+1){
          fa[ed]=q;
          return;
        }
        len[++ccnt]=len[p]+1;
        for(int i=1;i<=26;i++)mp[ccnt][i]=mp[q][i];
        fa[ccnt]=fa[q];
        fa[q]=ccnt;
        fa[ed]=ccnt;
        for(int i=p;mp[i][x]==q;i=fa[i])mp[i][x]=ccnt;
    }
    inline void build(){
      for(int i=2;i<=ccnt;i++)add(fa[i],i);
    }
    inline void dfs(int x){
      for(int i=head[x];i;i=nxt[i])
        dfs(to[i]),siz[x]+=siz[to[i]];
      if(siz[x]==k&&len[fa[x]]+1<=len[x])d[len[fa[x]]+1]++,d[len[x]+1]--;
    }
};
SAM sam;
int main(){
    int i,j,t;
    scanf("%d",&t);
    while(t--){
      sam.init();
      scanf("%s",s+1);
      n=strlen(s+1);
      scanf("%d",&k);
      for(i=1;i<=n;i++)sam.ins(s[i]-a+1,i);
      sam.build();
      sam.dfs(1);
      for(i=1;i<=n;i++){
          d[i]+=d[i-1];
          if(d[i]&&d[i]>=mx){
            mx=d[i];
            ans=i;
        }
      }
      printf("%d
",ans?ans:-1);
    }
    return 0;
}

以上是关于p5341 [TJOI2019]甲苯先生和大中锋的字符串的主要内容,如果未能解决你的问题,请参考以下文章

[TJOI2019]甲苯先生和大中锋的字符串

TJOI2019甲苯先生和大中锋的字符串

「TJOI2019」甲苯先生的滚榜

「TJOI2019」甲苯先生的滚榜

题解Luogu P5337 [TJOI2019]甲苯先生的字符串

luogu P5337 [TJOI2019]甲苯先生的字符串