hdu5769 Substring

除草、切了道水题

给定一个字符串和一个字符,求包含该字符的本质不同的字串个数

sa上对height和字符位置取个max加加就没了

#include<bits/stdc++.h>
#define rank _rank
using namespace std;
const int maxn=1e5+5;

int a[maxn],sa[maxn],rank[maxn],height[maxn];
void build_sa(int n){
	static int x[maxn],y[maxn],c[maxn];
	int m=26,k=1;
	memset(c,0,sizeof(*c)*(m+1));
	for(int i=1;i<=n;i++)c[x[i]=a[i]]++;
	for(int i=1;i<=m;i++)c[i]+=c[i-1];
	for(int i=n;i;i--)sa]--]=i;
	for(;k<=n;k<<=1){
		int tot=k;
		for(int i=n-k+1;i<=n;i++)y[i-n+k]=i;
		for(int i=1;i<=n;i++)
			if(sa[i]>k)y[++tot]=sa[i]-k;
		memset(c,0,sizeof(*c)*(m+1));
		for(int i=1;i<=n;i++)c[x[i]]++;
		for(int i=1;i<=m;i++)c[i]+=c[i-1];
		for(int i=n;i;i--)sa]]--]=y[i];
		for(int i=1;i<=n;i++)y[i]=x[i];
		tot=1;x[sa[1]]=1;
		for(int i=2;i<=n;i++){
			if(max(sa[i],sa[i-1])+k>n
					||y[sa[i]]!=y[sa[i-1]]
					||y[sa[i]+k]!=y[sa[i-1]+k])
				tot++;
			x[sa[i]]=tot;
		}
		if(tot==n)break;else m=tot;
	}
	for(int i=1;i<=n;i++)rank[sa[i]]=i;
	for(int i=1;i<=n;i++){
		height[rank[i]]=max(0,height[rank[i-1]]-1);
		if(rank[i]==1)continue;
		int j=sa[rank[i]-1];
		while(max(i,j)+height[rank[i]]<=n
				&&a[i+height[rank[i]]]==a[j+height[rank[i]]])
			height[rank[i]]++;
	}
}

char s[maxn],ss;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		cin>>ss;
		scanf("%s",s+1);
		int n=strlen(s+1);
		vector<int>vec;
		for(int i=1;i<=n;i++){
			a[i]=s[i]-'a';
			if(s[i]==ss)
				vec.push_back(i);
		}
		build_sa(n);
		long long ans=0;
		for(int i=1;i<=n;i++){
			int x=height[i];
			int len=n-sa[i]+1;
			int p=lower_bound(vec.begin(),vec.end(),sa[i])-vec.begin();
			if(p==vec.size())continue;
			x=max(x,vec[p]-sa[i]);
			ans+=len-x;
		}
		static int t=0;
		printf("Case #%d: ",++t);
		cout<<ans<<endl;
	}
	return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注