zoukankan      html  css  js  c++  java
  • [BJWC2010]外星联络

    XIII.[BJWC2010]外星联络

    和上题一样,没啥好说的,直接建出笛卡尔树即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int stk[500100],tp,L[500100],R[500100],id,pt;
    namespace Suffix_Array{
    	const int N=500100;
    	int x[N],y[N],sa[N],ht[N],rk[N],buc[N],n,m;
    	char s[N];
    	bool mat(int a,int b,int k){
    		if(y[a]!=y[b])return false;
    		if((a+k<n)^(b+k<n))return false;
    		if((a+k<n)&&(b+k<n))return y[a+k]==y[b+k];
    		return true;
    	}
    	void SA(){
    		for(int i=0;i<n;i++)buc[x[i]=s[i]]++;
    		for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
    		for(int i=n-1;i>=0;i--)sa[--buc[x[i]]]=i;
    		for(int k=1;k<n;k<<=1){
    			int num=0;
    			for(int i=n-k;i<n;i++)y[num++]=i;
    			for(int i=0;i<n;i++)if(sa[i]>=k)y[num++]=sa[i]-k;
    			for(int i=0;i<=m;i++)buc[i]=0;
    			for(int i=0;i<n;i++)buc[x[y[i]]]++;
    			for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
    			for(int i=n-1;i>=0;i--)sa[--buc[x[y[i]]]]=y[i],y[i]=0;
    			swap(x,y);
    			x[sa[0]]=num=0;
    			for(int i=1;i<n;i++)x[sa[i]]=mat(sa[i],sa[i-1],k)?num:++num;
    			m=num;
    		}
    		for(int i=0;i<n;i++)rk[sa[i]]=i;
    		for(int i=0,k=0;i<n;i++){
    			if(!rk[i])continue;
    			if(k)k--;
    			int j=sa[rk[i]-1];
    			while(j+k<n&&i+k<n&&s[j+k]==s[i+k])k++;
    			ht[rk[i]]=k;
    		}
    	}	
    }
    using namespace Suffix_Array;
    int mn[500100][20],LG[500100];
    int MIN(int i,int j){
    	return ht[i]<=ht[j]?i:j;
    }
    int RMQ(int l,int r){
    	int k=LG[r-l+1];
    	return MIN(mn[l][k],mn[r-(1<<k)+1][k]);
    }
    void solve(int l,int r,int las){
    //	printf("%d %d %d\n",l,r,las);
    	if(l>r)return;
    	int mp=RMQ(l,r);
    	for(int j=las;j<ht[mp];j++)printf("%d\n",r-l+2);
    	solve(l,mp-1,ht[mp]),solve(mp+1,r,ht[mp]);
    }
    int main(){
    	scanf("%d%s",&n,s),m='1';
    	SA();
    	for(int i=2;i<n;i++)LG[i]=LG[i>>1]+1;
    	for(int i=1;i<n;i++)mn[i][0]=i;
    	for(int j=1;j<=LG[n-1];j++)for(int i=1;i+(1<<j)-1<n;i++)mn[i][j]=MIN(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
    	solve(1,n-1,0);
    	return 0;
    }
    /*
    aabbababb
    1 12
    */
    

  • 相关阅读:
    [原创]用C++类实现单向链表的增删查和反转操作
    [原创]c语言中const与指针的用法
    [原创]大连sap vt 实习生面试经历
    Android studio 相关错误处理
    Java 判断整数方法
    Android 网络编程
    Android 基础篇(二)
    Android ListView 的基本应用,包括缓存
    Java重点识记
    Android基础篇(一)
  • 原文地址:https://www.cnblogs.com/Troverld/p/14605211.html
Copyright © 2011-2022 走看看