zoukankan      html  css  js  c++  java
  • bzoj4310

    题解:

    后缀数组求出本质不同的串

    然后二分答案

    贪心判断是否可行

    代码:

    #include<bits/stdc++.h>
    const int N=100010;
    using namespace std;
    typedef long long ll;
    char s[N];
    ll L,R,mid;
    int K,n,rk[N],sa[N],height[N],tmp[N],cnt[N],Log[N];
    int f[16][N],g[N],len,nowl,nowr,ansl,ansr;
    void SA(int n,int m)
    {
          n++;
          for (int i=0;i<n;i++)cnt[rk[i]=s[i]]++;
          for (int i=1;i<m;i++)cnt[i]+=cnt[i-1];
          for (int i=0;i<n;i++)sa[--cnt[rk[i]]]=i;
          for (int k=1;k<=n;k<<=1)
           {
            for (int i=0;i<n;i++)
             {
                  int j=sa[i]-k;
                  if (j<0)j+=n;
                  tmp[cnt[rk[j]]++]=j;
               }
              int j=0; 
            sa[tmp[cnt[0]=0]]=j=0;
            for (int i=1;i<n;i++)
             {
                  if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i;
                 sa[tmp[i]]=j;
             }
            memcpy(rk,sa,n*sizeof(int));
            memcpy(sa,tmp,n*sizeof(int));
            if (j>=n-1)break;
           }
          for (int i,k,j=rk[height[i=k=0]=0];i<n-1;i++,k++)
         while (~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1];
    }
    int lcp(int x,int y)
    {
          if (x==y)return n-x;
          x=rk[x],y=rk[y];
          if (x>y)swap(x,y);
          int k=Log[y-x];
          return min(f[k][x+1],f[k][y-(1<<k)+1]);
    }
    void kth(ll k)
    {
          ll s=0;
          for (int i=1;i<=n;s+=n-sa[i]-height[i],i++)
         if (s+n-sa[i]-height[i]>=k)
          {
            nowl=sa[i],nowr=nowl+height[i]+k-s-1;
            len=nowr-nowl+1;
            return;
            }
    }
    int ask(int l,int r)
    {
          int t=min(lcp(l,nowl),min(r-l+1,len));
          if (t==r-l+1&&t<=len)return 1;
          if (t==len)return 0;
          return s[l+t]<=s[nowl+t];
    }
    int check()
    {
        int j,k=0;
          for (int i=n-1;~i;i=j,k++)
         {
            for (j=i;~j;j--)
             if (!ask(j,i))break;
            if (j==i)return 0;
            }
      return k<=K;
    }
    int main()
    {
          scanf("%d%s",&K,s);
          n=strlen(s);
         SA(n,128);
          for (int i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
          for (int i=1;i<=n;i++)f[0][i]=height[i];
          for (int j=1;j<17;j++)
         for (int i=1;i+(1<<j-1)<=n;i++)f[j][i]=min(f[j-1][i],f[j-1][i+(1<<j-1)]);
          for (int i=1;i<=n;i++)R+=n-sa[i]-height[i];
         while (L<=R)
         {
            kth(mid=(L+R)>>1);
            if (check())ansl=nowl,ansr=nowr,R=mid-1;
            else L=mid+1;
           }
          for (int i=ansl;i<=ansr;i++)putchar(s[i]);
          return 0;
    }
  • 相关阅读:
    android开发之重写Application类
    android开发之Parcelable使用详解
    android开发之Bundle使用
    android开发之gridlayout使用入门
    android开发之merge结合include优化布局
    android开发布局优化之ViewStub
    android开发之PreferenceScreen使用详解
    android开发之使用Messenger实现service与activity交互
    LeetCode All in One 题目讲解汇总(持续更新中...)
    JavaWeb知识点总结
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8503697.html
Copyright © 2011-2022 走看看