zoukankan      html  css  js  c++  java
  • Poj1743 Musical Theme

    题目传送门

    题意:对一个序列的差分求出现至少两次且两次不相交的最长子串

    也是SA和SAM都可以做,SA稍微麻烦

    SA做法:二分+height分段rmq

    SAM做法(太神了):对于每个节点的right集合,求出其中的最大值和最小值

    那么合法的长度一定为min(mx[x],r[x]-l[x])(l和r分别是最大值和最小值)

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 40005
    using namespace std;
    int s[N][180],mx[N],sz[N],f[N],a[N];
    int n,m,lst=1,cnt=1,v[N],w[N],l[N],r[N];
    inline int extend(int c){
    	int p=lst,np=lst=++cnt,q,nq;
    	mx[np]=mx[p]+1; sz[np]=1; l[np]=r[np]=mx[np];
    	for(;p&&!s[p][c];p=f[p]) s[p][c]=np;
    	if(!p) return f[np]=1;
    	q=s[p][c];
    	if(mx[q]==mx[p]+1) f[np]=q;
    	else{
    		nq=++cnt;
    		mx[nq]=mx[p]+1;
    		f[nq]=f[q]; f[q]=f[np]=nq;
    		memcpy(s[nq],s[q],180<<2);
    		for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq;
    	}
    }
    int _18520(){
    	scanf("%d",&n); int ans=0; lst=cnt=1;
    	if(!n) return 0;
    	memset(l,127,sizeof(l));
    	memset(r,0,sizeof(r));
    	memset(v,0,sizeof(v));
    	memset(mx,0,sizeof(mx));
    	memset(f,0,sizeof(f));
    	memset(s,0,sizeof(s));
    	for(int i=1;i<=n;++i) scanf("%d",a+i);
    	for(int i=1;i<n;++i) a[i]=a[i+1]-a[i]+88; --n;
    	for(int i=1;i<=n;++i) extend(a[i]);
    	for(int i=1;i<=cnt;++i) ++v[mx[i]];
    	for(int i=1;i<=n;++i) v[i]+=v[i-1];
    	for(int i=cnt;i;--i) w[v[mx[i]]--]=i;
    	for(int p,i=cnt;i;--i){
    		p=w[i]; sz[f[p]]+=sz[p];
    		l[f[p]]=min(l[f[p]],l[p]);
    		r[f[p]]=max(r[f[p]],r[p]);
    	}
    	for(int i=cnt;i;--i) ans=max(ans,min(mx[i],r[i]-l[i]));
    	if(ans<4) puts("0"); else printf("%d
    ",++ans); return 1;
    }
    int main(){ while(_18520()); }

  • 相关阅读:
    细节回顾 p标签的嵌套问题
    面向对象编程
    深浅拷贝
    数据交互 jsonp插件
    数据交互 跨域问题
    数据交互 axios
    数据交互 jQuery ajax
    数据交互 后端代码
    数据交互 http请求 xhr
    Windows安装Node.js报错:2503、2502的解决方法
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8312612.html
Copyright © 2011-2022 走看看