1
8
2016
0

【poj3415】Common Substrings

题意:给你两个字符串和k,求不小于k的公共子串的个数。

计算A的某个后缀与B的某个后缀的最长公共前缀L,如果L大于等于k,就加上L-k+1。

我们先把B复制到A后面,并加一个分隔符。

我们考虑同一组大于等于k的height,对于每个B计算之前每个A对其的贡献,对于每个A计算之前每个B对其的贡献。但这样是N2的。所以,我们利用lcp的性质,i~j所有height的最小值,所以我们只要维护一个单调递增的栈即可。

代码:

 

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int K,l,n,top;
ll sum,ans;
int wa[200100],wb[200100],ws[200100],wv[200100],sa[200100],rank[200100],r[200100],height[200100],f[200100],a[200100],b[200100];
char s[200100];
int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(int *r,int *sa,int n,int m)
{
	int i,j,p,*x=wa,*y=wb,*t;
	for (i=0;i<m;i++) ws[i]=0;
	for (i=0;i<n;i++) ws[x[i]=r[i]]++;
	for (i=1;i<m;i++) ws[i]+=ws[i-1];
	for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
	for (j=1,p=1;p<n;j*=2,m=p)
	{
		p=0;
		for (i=n-j;i<n;i++) y[p++]=i;
		for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
		for (i=0;i<n;i++) wv[i]=x[y[i]];
		for (i=0;i<m;i++) ws[i]=0;
		for (i=0;i<n;i++) ws[wv[i]]++;
		for (i=1;i<m;i++) ws[i]+=ws[i-1];
		for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
		for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
			x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
	}
}
void calheight(int *r,int *sa,int n)
{
	int i,j,k=0;
	for (i=1;i<=n;i++) rank[sa[i]]=i;
	for (i=0;i<n;height[rank[i++]]=k)
		for (k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
int main()
{
	while (1)
	{
		scanf("%d",&K);
		if (!K) break;
		scanf("%s",s);
		l=strlen(s);
		s[l]=1;;
		scanf("%s",s+l+1);
		n=strlen(s);
		for (int i=0;i<n;i++) r[i]=s[i];
		r[n]=0;
		da(r,sa,n+1,200);
		calheight(r,sa,n);
		for (int i=2;i<=n;i++)
		{
			f[i]=(sa[i]<l);
			height[i]-=K-1;
			if (height[i]<0) height[i]=0;
		}
		height[n+1]=0;
		a[0]=-1;ans=0;
		for (int id=0;id<=1;id++)
		{
			sum=0,top=0;
			for (int i=2;i<=n;i++)
			{
				if (f[i]!=id) ans+=sum;
				a[++top]=height[i+1];
				b[top]=(f[i]==id);
				sum+=(ll)a[top]*b[top];
				while (a[top-1]>=a[top])
				{
					sum-=(ll)(a[top-1]-a[top])*b[top-1];
					a[top-1]=a[top];
					b[top-1]+=b[top];
					top--;
				}
			}
		}
		printf("%lld\n",ans);
	}
}
Category: 后缀数组 | Tags: | Read Count: 235

登录 *


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

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com