zoukankan      html  css  js  c++  java
  • 【bzoj4310】跳蚤

    • 题解:

      • 读了半个小时题。。。首先明确题意:求$S$分成至多$k$个串,每个串的子串的最大字典序的最大字典序(要选两次最大)最小
      • 求出sa和ht,本质不同的子串的个数等于总个数减去$sa$里面前后相同的个数:$sum = sum len - sa[i] - ht[i] $
      • 因为在后缀数组中本质相同的子串一定出现在$sa$的连续一段的$lcp$里;
      • 二分本质不同的串为第mid个,可以利用上面的结论$O(n)$求出第mid个串是什么;
      • 从后往前贪心,能不放就不放,比较两个串可以先求$lcp$再$O(1)$比较
      • 所以是$O(N logN)$的
         1 #include<cstdio>
         2 #include<iostream>
         3 #include<cstring>
         4 #define Run(i,l,r) for(int i=l;i<=r;i++)
         5 #define Don(i,l,r) for(int i=l;i>=r;i--)
         6 using namespace std;
         7 typedef long long ll;
         8 const int N=100010;
         9 int n,k,m,sa[N],ht[N],rk[N],c[N],x[N],y[N],b[N],f[N][20],lg[N],ansl,ansr;
        10 char s[N];
        11 void build_sa(){
        12     m=128;
        13     for(int i=0;i<m;i++) c[i]=0;
        14     for(int i=0;i<n;i++) c[x[i]=s[i]]++;
        15     for(int i=1;i<m;i++) c[i]+=c[i-1];
        16     for(int i=n-1;~i;i--) sa[--c[x[i]]]=i;
        17     int p;
        18     //for(int i=0;i<n;i++) cout<<sa[i]<<endl;cout<<endl;
        19     for(int k=1;k<n;k<<=1){
        20         p=0;
        21         for(int i=n-k;i<n;i++) y[p++]=i;
        22         for(int i=0;i<n;i++) if(sa[i]>=k)y[p++]=sa[i]-k;
        23         for(int i=0;i<m;i++) c[i]=0;
        24         for(int i=0;i<n;i++) c[x[y[i]]]++;
        25         for(int i=1;i<m;i++) c[i]+=c[i-1];
        26         for(int i=n-1;~i;i--) sa[--c[x[y[i]]]]=y[i];
        27         swap(x,y); p=1;x[sa[0]]=0;
        28         for(int i=1;i<n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?p-1:p++;
        29         if(p>=n) break; 
        30         m=p+1;
        31     //    for(int i=0;i<n;i++) cout<<sa[i]<<endl;cout<<endl;
        32     }
        33 }////////////////
        34 void build_ht(){
        35     for(int i=0;i<n;i++)rk[sa[i]]=i;
        36     for(int i=0,k=0,j;i<n;ht[rk[i++]]=k)
        37     for(k?k--:0,j=sa[rk[i]-1];rk[i]&&s[i+k]==s[j+k];k++);
        38 }/////
        39 void rmq(){
        40     lg[1]=0;for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
        41     for(int i=0;i<=n;i++) f[i][0]=ht[i];
        42     for(int i=1;i<17;i++)
        43     for(int j=0;j+(1<<i)<=n;j++)
        44     f[j][i]=min(f[j][i-1],f[j+(1<<i-1)][i-1]);
        45 }////
        46 int lcp(int x,int y){
        47     if(x==y)return n-x;////
        48     x=rk[x],y=rk[y]; 
        49     if(x>y) swap(x,y);
        50     int t=lg[y-x];
        51     int tmp;
        52     tmp=min(f[x+1][t],f[y-(1<<t)+1][t]);///
        53 //    printf("%d %d %d
        ",x,y,tmp);
        54     return tmp;
        55 }/////
        56 int l,r,len;
        57 void find(ll k){
        58     int i;
        59     for(i=1;i<=n;k-=b[i++])////
        60     if(b[i]>=k){l=sa[i],r=sa[i]+ht[i]+k-1;len=r-l+1;break;}///
        61     //printf("%d
        ",i);
        62 }/////
        63 bool ask(int L,int R){
        64     int Len=R-L+1;
        65     int t=min(min(len,Len),lcp(l,L));
        66     if(t==Len&&t<=len) return 1;
        67     if(t==len) return 0;
        68     return s[l+t]>s[L+t];////
        69 }////
        70 bool check(){
        71     int i,j,cnt=0;
        72     for(i=j=n-1;~i;i=j,cnt++){
        73         while(~j&&ask(j,i))j--;
        74         if(j==i||cnt>k)return 0;
        75       //    printf("%d
        ",j);
        76     }
        77 //    printf("
        ");
        78     return cnt<=k;
        79 }/////
        80 int main()
        81 {    //freopen("bzoj4310.in","r",stdin);
        82     //freopen("bzoj4310.out","w",stdout);
        83     scanf("%d",&k);
        84     scanf("%s",s); n=strlen(s); s[n++]=0;
        85     build_sa(); build_ht(); rmq();//
        86     ll L=1,R=0,mid;  n--;
        87     for(int i=1;i<=n;i++) R+=(b[i]=n-sa[i]-ht[i]);///
        88     while(L<=R){ 
        89         find(mid=L+R>>1);
        90         if(check())ansl=l,ansr=r,R=mid-1;else L=mid+1;//
        91     }
        92     for(int i=ansl;i<=ansr;i++)putchar(s[i]);//
        93     return 0;
        94 }//by tkys_Austin;
        bzoj4310
  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10222697.html
Copyright © 2011-2022 走看看