zoukankan      html  css  js  c++  java
  • LG2852/BZOJ1717 「USACO2006DEC」Milk Patterns 离散化+后缀数组

    问题描述

    LG2852


    题解

    字符串性质:字符串(s)的每个字串等于每个后缀的所有前缀

    对输入的东西离散化,然后把数值看做(mathrm{ASCII})后缀排序

    二分答案,二分长度。

    显然一段相同的字串,一定是连续一段后缀的公共前缀。

    如此(check)即可。


    (mathrm{Code})

    #include<bits/stdc++.h>
    using namespace std;
    
    #define maxn 20007
    
    void read(int &x){
    	x=0;char ch=1;int fh;
    	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    	if(ch=='-') fh=-1,ch=getchar();
    	else fh=1;
    	while(ch>='0'&&ch<='9'){
    		x=(x<<1)+(x<<3)+ch-'0';
    		ch=getchar();
    	}
    	x*=fh;
    }
    
    struct node{
    	int val,id,New;
    }st[maxn];
    
    int sa[maxn],n,m,ct[maxn],x[maxn],y[maxn],tot;
    int hei[maxn];
    int a[maxn],cnt,rk[maxn];
    int low,l,r,mid,ans;
    
    bool comp(node a,node b){
    	return a.val<b.val;
    }
    
    bool cmp(node a,node b){
    	return a.id<b.id;
    }
    
    void preprocess(){
    	sort(st+1,st+n+1,comp);
    	for(register int i=1;i<=n;i++){
    		if(i==1||(i>1&&st[i].val>st[i-1].val)){
    			m++;
    		}
    		st[i].New=m;
    	}
    	sort(st+1,st+n+1,cmp);
    	for(register int i=1;i<=n;i++){
    		a[i]=st[i].New;
    	}
    	++m;
    }
    
    void SA(){
    	for(register int i=1;i<=n;i++) ct[x[i]=a[i]]++;
    	for(register int i=2;i<=m;i++) ct[i]+=ct[i-1];
    	for(register int i=n;i>=1;i--) sa[ct[x[i]]--]=i;
    	for(register int k=1;k<=n;k<<=1){
    		int tot=0;
    		for(register int i=n-k+1;i<=n;i++) y[++tot]=i;
    		for(register int i=1;i<=n;i++) if(sa[i]>k) y[++tot]=sa[i]-k;
    		for(register int i=1;i<=m;i++) ct[i]=0;
    		for(register int i=1;i<=n;i++) ct[x[i]]++;
    		for(register int i=1;i<=m;i++) ct[i]+=ct[i-1];
    		for(register int i=n;i>=1;i--) sa[ct[x[y[i]]]--]=y[i],y[i]=0;
    		swap(x,y);x[sa[1]]=tot=1;
    		for(register int i=2;i<=n;i++)
    			if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) x[sa[i]]=tot;
    			else x[sa[i]]=++tot;
    		if(tot==n) break;
    		m=tot;
    	}
    }
    
    void HEIGHT(){
    	int tmp=0;
    	for(register int i=1;i<=n;i++) rk[sa[i]]=i;
    	for(register int i=1;i<=n;i++){
    		if(rk[i]==1) continue;
    		if(tmp) --tmp;
    		int j=sa[rk[i]-1];
    		while(j+tmp<=n&&i+tmp<=n&&a[i+tmp]==a[j+tmp]) ++tmp;
    		hei[rk[i]]=tmp;
    	}
    }
    
    bool check(){
    	if(mid==0) return true;
    	int lst=0;
    	for(register int i=1;i<=n;i++){
    		if(hei[i]<mid){//错误笔记:将mid写为m,以后check写传参式的 
    			if(i-lst>=low) return true;
    			lst=i;
    		}
    	}
    	if(n+1-lst>=low) return true;
    	return false;
    }
    
    int main(){
    	read(n);read(low);
    	for(register int i=1;i<=n;i++){
    		read(st[i].val);st[i].id=i;
    	}
    	preprocess();
    	SA();HEIGHT();
    	l=0,r=n;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(check()) ans=mid,l=mid+1;
    		else r=mid-1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    去年课程设计的作品
    终于结束了期末考试
    记在园子里安家
    ASP.NET中实现无刷新级联
    ASP.NET中利用JQuery AJAX修改用户密码
    The LogStructured MergeTree(译)(转载)
    我常用的Latex中文报告模板(一)
    LRU算法的简单实现( C语言 + uthash包)
    epoll 使用详解
    转载系列之一:浅析Hadoop文件格式
  • 原文地址:https://www.cnblogs.com/liubainian/p/11484892.html
Copyright © 2011-2022 走看看