zoukankan      html  css  js  c++  java
  • bzoj 4310 跳蚤

    后缀数组+二分

    1.

    从后往前贪心扫

    当必须分的时候就分一段

    注意比较两个串大小时的细节

    2.

    先二分这个串第一次出现时在后缀数组上的位置

    再二分具体是哪个串

    从前往后扫,使右端点不断往左缩,当 右<=左 时分一段

    快的飞起

    1.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 200005
    #define ll long long
    using namespace std;
    char s[N];
    int rk[N],sa[N],wb[N],sum[N];
    void sasa(int n,int m)
    {
    	int *x=rk,*y=wb;
    	for(int i=0;i<m;i++)sum[i]=0;
    	for(int i=0;i<n;i++)sum[x[i]=s[i]]++;
    	for(int i=1;i<m;i++)sum[i]+=sum[i-1];
    	for(int i=n-1;i>=0;i--)sa[--sum[x[i]]]=i;
    	for(int j=1,p=1;p<n;m=p,j<<=1)
    	{
    		p=0;
    		for(int i=n-j;i<n;i++)y[p++]=i;
    		for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
    		for(int i=0;i<m;i++)sum[i]=0;
    		for(int i=0;i<n;i++)sum[x[i]]++;
    		for(int i=1;i<m;i++)sum[i]+=sum[i-1];
    		for(int i=n-1;i>0;i--)sa[--sum[x[y[i]]]]=y[i];
    		swap(x,y);x[sa[0]]=0;p=1;
    		for(int i=1;i<n;i++)
    			x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]?p-1:p++;
    	}
    	return ;
    }
    int h[N];
    void calh(int n)
    {
    	for(int i=1;i<=n;i++)rk[sa[i]]=i;
    	int k=0;
    	for(int i=0;i<n;i++)
    	{
    		if(k)k--;
    		int j=sa[rk[i]-1];
    		while(s[j+k]==s[i+k])k++;
    		h[rk[i]]=k;
    	}
    	return ;
    }
    int mn[N][20],lg[N],n;
    void ST()
    {
    	lg[0]=-1;
    	for(int i=1;i<=100000;i++)lg[i]=lg[i>>1]+1;
    	for(int i=1;i<=n;i++)mn[i][0]=h[i];
    	for(int i=1;i<20;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			if(j+(1<<(i-1))<=n)
    			{
    				mn[j][i]=min(mn[j][i-1],mn[j+(1<<(i-1))][i-1]);
    			}
    			else mn[j][i]=mn[j][i-1];
    		}
    	}return ;
    }
    int qur(int l,int r)
    {
    	int k=lg[r-l+1];
    	return min(mn[l][k],mn[r-(1<<k)+1][k]);
    }
    bool cmp(int x,int len1,int y,int len2)
    {
    	if(x<y)
    	{
    		int p=qur(x+1,y);
    		if(p>=len2&&p<len1)return 0;
    		return 1;
    	}
    	else if(x>y)
    	{
    		int p=qur(y+1,x);
    		if(p>=len1)return 1;
    		return 0;
    	}
    	else
    	{
    		if(len1<=len2)return 1;
    		return 0;
    	}
    }
    int k;
    bool pan(ll x)
    {
    	int now=1;ll tot=0;
    	int pos,len;
    	for(int i=1;i<=n;i++)
    	{
    		ll pre=tot;
    		tot+=n-sa[i]-h[i];
    		if(tot>=x)
    		{
    			pos=i;len=h[i]+x-pre;
    			break;
    		}
    	}
    	int ta=n-1;
    	for(int i=n-1;i>=0;i--)
    	{
    		if(!cmp(rk[i],1,pos,len))return 0;
    		if(!cmp(rk[i],ta-i+1,pos,len))
    		{
    			ta=i,now++;
    		}
    	}
    	return now<=k;
    }
    int main()
    {
    	scanf("%d",&k);
    	scanf("%s",s);
    	n=strlen(s);
    	sasa(n+1,256);
    	calh(n);
    	ST();
    	ll sm=1LL*n*(n+1)/2;
    	for(int i=1;i<=n;i++)sm-=h[i];
    	ll l=1,r=sm;
    	while(l<r)
    	{
    		ll mid=(l+r)>>1;
    		if(pan(mid))r=mid;
    		else l=mid+1;
    	}
    	ll tot=0;
    	int pos,len;
    	for(int i=1;i<=n;i++)
    	{
    		ll pre=tot;
    		tot+=n-sa[i]-h[i];
    		if(tot>=l)
    		{
    			pos=i;len=h[i]+l-pre;
    			break;
    		}
    	}
    	for(int i=0;i<len;i++)
    	{
    		putchar(s[sa[pos]+i]);
    	}puts("");
    	return 0;
    }
    

    2.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 200005
    using namespace std;
    char s[N];
    int c[N],sa[N],m,n,rk[N],t1[N],t2[N],v[N];
    void saa(char *s,int n,int m)
    {
        int *x=t1,*y=t2;
        for(int i=0;i<m;i++)c[i]=0;
        for(int i=0;i<n;i++)c[x[i]=s[i]]++;
        for(int i=1;i<m;i++)c[i]+=c[i-1];
        for(int i=0;i<n;i++)sa[--c[x[i]]]=i;
        int p=1;
        for(int j=1;p<n;j<<=1,m=p)
        {
            p=0;
            for(int i=n-j;i<n;i++)y[p++]=i;
            for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
            for(int j=0;j<m;j++)c[j]=0;
            for(int i=0;i<n;i++)c[x[i]]++;
            for(int j=1;j<m;j++)c[j]+=c[j-1];
            for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
            swap(x,y);x[sa[0]]=0;p=1;
            for(int i=1;i<n;i++)
              x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]?p-1:p++;
        }
        return ;
    }
    int h[N];
    void calh(int n)
    {
        for(int i=1;i<=n;i++)rk[sa[i]]=i;
        int k=0;
        for(int i=0;i<n;i++)
        {
            if(k)k--;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k])k++;
            h[rk[i]]=k;
        }
        return ;
    }
    int main()
    {
        scanf("%d %s",&m,s);
        n=strlen(s);s[n]=0;
        saa(s,n+1,300);
        calh(n);
        int l=1,r=n;
        while(l<r)
        {
            int mid=(l+r)>>1,num=0,mn=n,m1=n;
            for(int i=mid+1;i<=n;i++){m1=min(m1,h[i]);v[sa[i]]=m1;if(!h[i])num=m+1;}
            for(int i=0;i<=n-1;i++)
            {
                if(mn==i)num++,mn=n;
                if(v[i])mn=min(mn,i+v[i]);
            }
            if(num+1<=m)r=mid;else l=mid+1;
            for(int i=mid+1;i<=n;i++)v[sa[i]]=0; 
        }
        int u=l;
        l=h[u]+1,r=n-sa[u];     
        while(l<r)
        {
             int mid=(l+r)>>1,k=u,num=0,mn=n,m1=mid;
             for(int i=u+1;i<=n;i++){m1=min(m1,h[i]);v[sa[i]]=m1;}
             v[sa[u]]=mid;
             for(int i=0;i<n;i++)
             {
                if(mn==i)num++,mn=n;
                if(v[i])mn=min(mn,i+v[i]);
             }
             if(num+1<=m)r=mid;else l=mid+1;
             for(int i=k;i<=u;i++)v[sa[i]]=0;
        }
        for(int i=1;i<=l;i++)printf("%c",s[sa[u]+i-1]);
        puts("");
        return 0;
    }
    

      

  • 相关阅读:
    XAF 有条件的对象访问权限
    XAF 顯示 UnInplace Report(設置自定義條件顯示報表,不是根據選擇ListView記錄條件顯示報表)
    XAF 如何自定义PivotGrid单元格显示文本?
    XAF 如何布局详细视图上的按钮
    XAF How to set size of a popup detail view
    XAF Delta Replication Module for Devexpress eXpressApp Framework
    XAF 帮助文档翻译 EasyTest Basics(基础)
    XAF 用户双击ListView记录时禁止显示DetailView
    XAF How to enable LayoutView mode in the GridControl in List Views
    XAF 如何实现ListView单元格批量更改?
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6737036.html
Copyright © 2011-2022 走看看