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;
    }
    

      

  • 相关阅读:
    批量新增百万条数据 十百万条数据
    sqlserver 组内排序
    EF ++属性会更新实体
    Entity Framework Core: A second operation started on this context before a previous operation completed
    abp Cannot access a disposed object. A common cause of this error is disposing
    abp xunit Can not register IHostingEnvironment. It should be a non-abstract class. If not, it should be registered before.”
    hangfire enqueued but not processing(hangfire 定时任务入队列但不执行)
    EF 更新实体 The instance of entity type 'BabyEvent' cannot be tracked because another instance
    datatable to entiy list 不支持可空类型和枚举类型
    webapi 设置不显示接口到swaggerUI
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6737036.html
Copyright © 2011-2022 走看看