POJ3693 Maximum repetition substring 后缀数组
BZOJ2780:[Spoj]8093 Sevenk Love Oimaster 后缀自动机+离线+dfs序+树状数组

POJ3415 Common Substrings 后缀数组+单调栈

shinbokuow posted @ Jan 11, 2015 04:45:10 PM in BZOJ with tags 后缀数组 单调性 , 2065 阅读

思路:

最近好像是被<囚人的旋律>里的主人公的心情所影响,所以效率很低.

例如,这样一道傻逼题我居然傻逼了3个小时!

我整个人都单调栈了.

 

就是求个height,然后在连续块内,我们对于每个属于串A的后缀分别计算出在他前面的属于串B的后缀的影响,在计算出在他之后的属于B的后缀的影响.

然后我们从前到后,再从后到前扫描一边,利用一个单调栈维护一下属于串B的后缀即可.

说起来简单...不过写起来...一定是我太鶸了.

 

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;

#define N 200010
char s1[N],s2[N],s[N];int v[N],tv[N],q[N],c[N],sa[N];
inline bool cmp(int x,int y,int hl,int n){
	return v[x]==v[y]&&((x+hl>=n&&y+hl>=n)||(x+hl<n&&y+hl<n&&v[x+hl]==v[y+hl]));
}
inline void calcsa(char*s,int n,int m,int*sa){
	register int i,j,k;int id,hl;
	for(i=0;i<m;++i)c[i]=0;
	for(i=0;i<n;++i)++c[v[i]=s[i]];
	for(i=1;i<m;++i)c[i]+=c[i-1];
	for(i=n-1;i>=0;--i)sa[--c[v[i]]]=i;
	for(int d=1;;++d){
		for(hl=1<<(d-1),id=0,i=n-hl;i<n;++i)q[id++]=i;
		for(i=0;i<n;++i)if(sa[i]>=hl)q[id++]=sa[i]-hl;
		for(i=0;i<m;++i)c[i]=0;
		for(i=0;i<n;++i)++c[v[q[i]]];
		for(i=1;i<m;++i)c[i]+=c[i-1];
		for(i=n-1;i>=0;--i)sa[--c[v[q[i]]]]=q[i];
		for(i=m=0;i<n;i=j+1,++m){
			for(j=i;j<n-1&&cmp(sa[j],sa[j+1],hl,n);++j);
			for(k=i;k<=j;++k)tv[sa[k]]=m;
		}for(i=0;i<n;++i)v[i]=tv[i];
		if(m==n)break;
	}
}
int rk[N],h[N];
inline void calch(char*s,int n,int*sa,int*rk,int*h){
	register int i,j;
	for(i=0;i<n;++i)rk[sa[i]]=i;
	for(i=0;i<n;++i)if(rk[i]){
		j=max(0,h[rk[i-1]]-1);while(i+j<n&&sa[rk[i]-1]+j<n&&s[i+j]==s[sa[rk[i]-1]+j])++j;h[rk[i]]=j;
	}
}

int lim;

struct Case{
	int v,c;
	Case(){}
	Case(int _v,int _c):v(_v),c(_c){}
}stk[N];
int top,nowcnt;long long sum[N];int cnt[N];

int belong[N];
int main(){
	int i,j,k;
	while(scanf("%d",&lim)&&lim){
		scanf("%s%s",s1,s2);int len1=strlen(s1),len2=strlen(s2);
		memset(s,0,sizeof s);int len=0;for(i=0;i<len1;++i)belong[len]=1,s[len++]=s1[i];s[len++]='$';for(i=0;i<len2;++i)belong[len]=2,s[len++]=s2[i];
		calcsa(s,len,256,sa),calch(s,len,sa,rk,h);

		LL ans=0;int tmp;
		for(i=1;i<len;){
			if(h[i]>=lim){
				for(j=i;j<len&&h[j]>=lim;++j);
				for(top=0,h[i-1]=h[i],tmp=h[j],h[j]=h[j-1],k=i-1;k<j;++k){
					nowcnt=0;
					while(top&&stk[top].v>=h[k])nowcnt+=stk[top--].c;
					if(nowcnt)stk[++top]=Case(h[k],nowcnt),sum[top]=sum[top-1]+(LL)stk[top].c*stk[top].v,cnt[top]=cnt[top-1]+stk[top].c;
					if(belong[sa[k]]==2)ans+=sum[top]-(LL)cnt[top]*(lim-1);
					else{
						nowcnt=1;while(top&&stk[top].v>=h[k+1])nowcnt+=stk[top--].c;
						stk[++top]=Case(h[k+1],nowcnt),sum[top]=sum[top-1]+(LL)stk[top].c*stk[top].v,cnt[top]=cnt[top-1]+stk[top].c;
					}
					
				}
				for(top=0,k=j-1;k>=i-1;--k){
					nowcnt=0;
					while(top&&stk[top].v>=h[k+1])nowcnt+=stk[top--].c;
					if(nowcnt)stk[++top]=Case(h[k+1],nowcnt),sum[top]=sum[top-1]+(LL)stk[top].c*stk[top].v,cnt[top]=cnt[top-1]+stk[top].c;
					if(belong[sa[k]]==2)ans+=sum[top]-(LL)cnt[top]*(lim-1);
					else{
						nowcnt=1;while(top&&stk[top].v>=h[k])nowcnt+=stk[top--].c;
						stk[++top]=Case(h[k],nowcnt),sum[top]=sum[top-1]+(LL)stk[top].c*stk[top].v,cnt[top]=cnt[top-1]+stk[top].c;
					}
				}h[j]=tmp;
				i=j;
			}else++i;
		}
		cout<<ans<<endl;
	}
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter