zoukankan      html  css  js  c++  java
  • [cf1063F]String Journey

    设$f[i]$表示令$s=s[i,n]$且强制$u_{1}$为空所对应的答案,不难发现有$f[i]le f[i+1]+1$,暴力判断答案,时间复杂度为$o(ncdot 判断复杂度)$

    判断$f[i]$能否等于$k$,当且仅当存在$j$使得$jge i+k$、$f[j]ge k-1$且$max(lcp(i,j),lcp(i+1,j))ge k-1$,那么最终答案即为$max(f_{i})$

    这个可以用后缀数组来求,对于第3个条件保证其是线段树上的一个区间,第1个条件用可持久化线段树来维护并求出最大的$f[j]$即可,时间复杂度为$o(nlog_{2}n)$

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 500005
      4 #define L (k<<1)
      5 #define R (L+1)
      6 #define mid (l+r>>1)
      7 int V,n,ans,a[N],b[N],rk[N<<1],sa[N],h[N],f[N],r[N],mn[N<<2],ls[N*20],rs[N*20],mx[N*20];
      8 char s[N];
      9 bool cmp(int x,int y,int i){
     10     return (rk[x]==rk[y])&&(rk[x+i]==rk[y+i]);
     11 }
     12 void calc(){
     13     for(int i=0;i<n;i++)rk[i]=s[i]-'a'+1;
     14     int m=26;
     15     for(int i=1;i<n;i*=2){
     16         memset(a,0,sizeof(a));
     17         a[0]=i;
     18         for(int j=i;j<n;j++)a[rk[j]]++;
     19         for(int j=1;j<=m;j++)a[j]+=a[j-1];
     20         for(int j=n-1;j>=0;j--)b[a[rk[i+j]]--]=j;
     21         memset(a,0,sizeof(a));
     22         for(int j=0;j<n;j++)a[rk[j]]++;
     23         for(int j=1;j<=m;j++)a[j]+=a[j-1];
     24         for(int j=n;j;j--)sa[a[rk[b[j]]]--]=b[j];
     25         m=0;
     26         for(int j=1;j<=n;j++)
     27             if ((j>1)&&(cmp(sa[j-1],sa[j],i)))a[sa[j]]=m;
     28             else a[sa[j]]=++m;
     29         memcpy(rk,a,sizeof(a));
     30         if (n==m)break;
     31     }
     32     for(int i=0,j=0;i<n;h[rk[i++]]=j){
     33         if (rk[i]==1)continue;
     34         if (j)j--;
     35         for(int k=sa[rk[i]-1];(max(i,k)+j<n)&&(s[i+j]==s[k+j]);j++);
     36     }
     37     h[1]=0;
     38 }
     39 void build(int k,int l,int r){
     40     if (l==r){
     41         mn[k]=h[l];
     42         return;
     43     }
     44     build(L,l,mid);
     45     build(R,mid+1,r);
     46     mn[k]=min(mn[L],mn[R]);
     47 }
     48 int query(int k,int l,int r,int x,int y){
     49     if ((l>y)||(x>r))return 0x3f3f3f3f;
     50     if ((x<=l)&&(r<=y))return mn[k];
     51     return min(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
     52 }
     53 int query1(int k,int l,int r,int x,int y){//求在x左边第一个比y小的数
     54     if ((l>x)||(mn[k]>=y))return 0;
     55     if (l==r)return l;
     56     int ans=query1(R,mid+1,r,x,y);
     57     if (ans)return ans;
     58     return query1(L,l,mid,x,y);
     59 }
     60 int query2(int k,int l,int r,int x,int y){//求x右边第一个比y小的数 
     61     if ((r<x)||(mn[k]>=y))return n+1;
     62     if (l==r)return l;
     63     int ans=query2(L,l,mid,x,y);
     64     if (ans<=n)return ans;
     65     return query2(R,mid+1,r,x,y);
     66 }
     67 void update(int &k,int l,int r,int x,int y){
     68     mx[++V]=max(mx[k],y);
     69     ls[V]=ls[k];
     70     rs[V]=rs[k];
     71     k=V;
     72     if (l==r)return;
     73     if (x<=mid)update(ls[k],l,mid,x,y);
     74     else update(rs[k],mid+1,r,x,y);
     75 }
     76 int get(int k,int l,int r,int x,int y){
     77     if ((!k)||(l>y)||(x>r))return 0;
     78     if ((x<=l)&&(r<=y))return mx[k];
     79     return max(get(ls[k],l,mid,x,y),get(rs[k],mid+1,r,x,y));
     80 }
     81 int main(){
     82     scanf("%d%s",&n,s);
     83     calc();
     84     build(1,1,n);
     85     ans=f[n-1]=1;
     86     update(r[n-1],1,n,rk[n-1],1);
     87     for(int i=n-2;i>=0;i--){
     88         f[i]=f[i+1]+1;
     89         while (1){
     90             int l=query1(1,1,n,rk[i],f[i]-1),rr=query2(1,1,n,rk[i]+1,f[i]-1)-1;
     91             if (get(r[i+f[i]],1,n,l,rr)>=f[i]-1)break;
     92             l=query1(1,1,n,rk[i+1],f[i]-1),rr=query2(1,1,n,rk[i+1]+1,f[i]-1)-1;
     93             if (get(r[i+f[i]],1,n,l,rr)>=f[i]-1)break;
     94             f[i]--;
     95         }
     96         r[i]=r[i+1];
     97         update(r[i],1,n,rk[i],f[i]);
     98         ans=max(ans,f[i]);
     99     }
    100     printf("%d",ans);
    101 }
    View Code
  • 相关阅读:
    requireJS的优化工具 ---- r.js
    requireJS基本配置相关
    利用thread和sleep生成字符串的伪随机序列
    操作系统虚拟内存中的四种典型页替换算法(OPT,LRU,FIFO,Clock)
    考虑一个特殊的hash函数h,能将任一字符串hash成一个整数k……
    二叉树的遍历(C++非递归实现)
    判断一点是否在一条射线的左边
    如何判断单链表是否存在环
    移位数组的二分查找
    字符串相关函数的实现
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13844279.html
Copyright © 2011-2022 走看看