zoukankan      html  css  js  c++  java
  • poj 1743 Musical Theme【二分+SA】

    差分,然后二分长度mid,判断是把height按照min不小于mid分组,取最大最小的sa位置看是否>=mid即可,注意差分后最后答案要+1

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=50005;
    int n,a[N],r[N],wa[N],wb[N],wsu[N],wv[N],sa[N],rk[N],he[N];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    bool cmp(int r[],int a,int b,int l)
    {
    	return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void saa(int r[],int n,int m)
    {
    	int *x=wa,*y=wb;
    	for(int i=0;i<=m;i++)
    		wsu[i]=0;
    	for(int i=1;i<=n;i++)
    		wsu[x[i]=r[i]]++;
    	for(int i=1;i<=m;i++)
    		wsu[i]+=wsu[i-1];
    	for(int i=n;i>=1;i--)
    		sa[wsu[x[i]]--]=i;
    	for(int j=1,p=1;j<n&&p<n;j<<=1,m=p)
    	{
    		p=0;
    		for(int i=n-j+1;i<=n;i++)
    			y[++p]=i;
    		for(int i=1;i<=n;i++)
    			if(sa[i]>j)
    				y[++p]=sa[i]-j;
    		for(int i=1;i<=n;i++)
    			wv[i]=x[y[i]];
    		for(int i=0;i<=m;i++)
    			wsu[i]=0;
    		for(int i=1;i<=n;i++)
    			wsu[wv[i]]++;
    		for(int i=1;i<=m;i++)
    			wsu[i]+=wsu[i-1];
    		for(int i=n;i>=1;i--)
    			sa[wsu[wv[i]]--]=y[i];
    		swap(x,y);
    		p=1;
    		x[sa[1]]=1;
    		for(int i=2;i<=n;i++)
    			x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
    	}
    	for(int i=1;i<=n;i++)
    		rk[sa[i]]=i;
    	for(int i=1,j,k=0;i<=n;he[rk[i++]]=k)
    		for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
    	// for(int i=1;i<=n;i++)
    	// {cerr<<he[i]<<endl;
    		// for(int j=sa[i];j<=n;j++)
    			// cerr<<r[j]<<" ";
    		// cerr<<endl;
    	// }
    }
    bool ok(int w)
    {//cerr<<w<<endl;
    	for(int i=2,la;i<=n;i=la+1)
    	{
    		int mn=sa[i-1],mx=sa[i-1];
    		la=i;
    		while(he[la]>=w)
    			mn=min(mn,sa[la]),mx=max(mx,sa[la]),la++;
    		// cerr<<mn<<" "<<mx<<endl;
    		if(mx-mn>=w)
    			return 1;
    	}
    	return 0;
    }
    int main()
    {
    	while(scanf("%d",&n)&&n)
    	{
    		for(int i=1;i<=n;i++)
    			a[i]=read();
    		for(int i=1;i<n;i++)
    			r[i]=a[i+1]-a[i]+88;
    		saa(r,n-1,200);
    		int l=0,r=n,ans=0;
    		while(l<=r)
    		{
    			int mid=(l+r)>>1;
    			if(ok(mid))
    				l=mid+1,ans=mid;
    			else
    				r=mid-1;
    		}//cerr<<ans<<endl;
    		printf("%d
    ",ans>=4?ans+1:0);
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOS开发快捷键
    通达信指标函数说明大全(2014)(转)
    windows下的wxWidgets环境配置
    Qt->数字格式化
    被称"硬盘杀手"的几个win7系统服务如何关闭(转)
    关闭系统索引(转)
    SSD固态硬盘优化(转)
    通达信的文件目录结构(转)
    Macdrive8破解版如何激活
    IOS6.0调用通讯录和之前的差别
  • 原文地址:https://www.cnblogs.com/lokiii/p/9988809.html
Copyright © 2011-2022 走看看