zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    USB设备驱动之设备初始化(设备枚举)
    clCreateCommandQueue&#39;: was declared deprecated
    Struts2 Result Type
    IOS屏幕旋转
    VMware Workstation 集群仲裁磁盘和数据共享磁盘的创建
    UNIX环境高级编程之第3章:文件I/O
    poj 1068 Parencodings(模拟)
    使用oracle数据库和MySQL数据库时hibernate的映射文件.hbm.xml的不同
    线程池的实现
    zoj 1648 Circuit Board
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/11519053.html
Copyright © 2011-2022 走看看