• CF1037H Security


    题意:给出一个字符串 (S) ,给出 (Q) 个操作,给出(L) , (R) , (T) ,求字典序最小的(S_1),使得(S_1)(S[L..R])的子串,且(S_1)的字典序严格大于(T)。输出这个(S_1),如果无解输出(-1)

    (SAM) + 线段树合并

    利用在 (parent树) 线段树合并维护 ({ m endpos}(p)) 并解决区间 ([l,r]) 限制。

    所以直接贪心地在 (SAM) 上跑,使跑出来的串尽可能接近 (T) ,即 (S_1,{ m strlen}(S_1)=n) 中的 ([1,n-1])(T)([1,n-1]) 时相同的,只有第 (n) 位是不同的。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define R register int 
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int N=1000010,B=30;
    int n,lst=1,tot=1,num;
    int len[N],fa[N],c[N][26],d[N],mem[N];
    char s[N],ans[N];
    inline void add(int ch) {
      R p=lst,np=lst=++tot;
      len[np]=len[p]+1;
      while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
      if(!p) return fa[np]=1,void();
      R q=c[p][ch];
      if(len[q]==len[p]+1) fa[np]=q;
      else {
        R nq=++tot;
        memcpy(c[nq],c[q],26<<2);
        fa[nq]=fa[q],len[nq]=len[p]+1;
        fa[np]=fa[q]=nq;
        while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
      }
    }
    int rt[N],ls[N*B],rs[N*B],sum[N*B];
    inline void change(int& tr,int l,int r,int p) {
      if(!tr) tr=++num;
      ++sum[tr]; if(l==r) return ;
      R md=(l+r)>>1;
      p<=md?change(ls[tr],l,md,p):change(rs[tr],md+1,r,p);
    }
    inline bool query(int tr,int l,int r,int LL,int RR) {
      if(LL<=l&&r<=RR) return sum[tr]; R md=(l+r)>>1;
      return (LL<=md&&ls[tr]&&query(ls[tr],l,md,LL,RR))
            ||(RR>md&&rs[tr]&&query(rs[tr],md+1,r,LL,RR));
    }
    inline int merge(int tr,int t,int l,int r) {
      if(!tr||!t) return tr+t;
      R p=++num,md=(l+r)>>1;
      sum[p]=sum[tr]+sum[t];
      if(l==r) return p;
      ls[p]=merge(ls[tr],ls[t],l,md);
      rs[p]=merge(rs[tr],rs[t],md+1,r);
      return p;
    }
    inline void solve(int l,int r) {
      R p=1,tot=1,m=strlen(s+1),ch;
      while(20040109) {
        ch=s[tot]-'a';
        ans[tot]='#';
        for(R i=max(ch+1,0);i<26;++i) 
          if(c[p][i]&&query(rt[c[p][i]],1,n,l+tot-1,r)) {
            ans[tot]=i+'a'; break;
          }
        if(tot==m+1||!c[p][ch]||
            !query(rt[c[p][ch]],1,n,l+tot-1,r)) break;
        p=c[p][ch];
        ++tot;
      } while(tot&&ans[tot]=='#') --tot; 
      if(!tot) return puts("-1"),void();
      for(R i=1;i<tot;++i) putchar(s[i]);
      putchar(ans[tot]),putchar(10);
    }
    inline void main() {
      scanf("%s",s+1),n=strlen(s+1);
      for(R i=1;i<=n;++i)   
        add(s[i]-'a'),change(rt[lst],1,n,i);
      for(R i=1;i<=tot;++i) ++d[len[i]];
      for(R i=1;i<=n;++i) d[i]+=d[i-1];
      for(R i=1;i<=tot;++i) mem[d[len[i]]--]=i;
      for(R i=tot;i;--i) { R u=mem[i];
        rt[fa[u]]=merge(rt[fa[u]],rt[u],1,n);
      } R T=g(); while(T--) {
        R l=g(),r=g();
        scanf("%s",s+1);
        solve(l,r);
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.10

  • 相关阅读:
    Eclipse 代码提示功能设置。
    eclipse android 查看源文件 出错的解决办法
    Android 中自定义控件和属性(attr.xml,declarestyleable,TypedArray)的方法和使用
    android屏幕尺寸 sp,px,dp,density,in介绍
    用C#实现的条形码和二维码编码解码器 之转载
    在Eclipse下如何导入jar安装包
    C# 获取往控件中拖进的文件或文件夹的信息(转)
    c#中Dictionary、ArrayList、Hashtable和数组的区别是什么?[转]
    C#中的枚举
    C#结构体特性
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12177610.html
Copyright © 2020-2023  润新知