题意:
给出一个串a,和n个串b,现在问a串的子串中在b中未出现的个数。
题解:
全部链接计算不同子串个数sum1,链接b串计算不同子串个数sum2,然后用sum1-sum2就是答案。
因为先计算全部的在计算b的,所以我们将a串存在最后面,这样在计算第二次的时候就可以很快处理。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } typedef __int64 ll; const int oo=0x3f3f3f3f; const ll OO=1LL<<61; const int MOD=2012; const int maxn=400105; const int maxm=100005; int Rank[maxn],SA[maxn],height[maxn]; int t1[maxn],t2[maxn],t3[maxn],t4[maxn]; char str[maxn],s2[maxn]; int ss[maxn]; int in[maxn],len[maxn]; void Swap(int*& a,int*& b){ int *temp=a; a=b; b=temp; } bool cmp(int t[],int a,int b,int l){ return t[a]==t[b]&&t[a+l]==t[b+l]; } void build_SA(int s[],int len,int up){ int *k1=t1,*k2=t2,*r=t3,*cnt=t4; for(int i=0;i<up;i++)cnt[i]=0; for(int i=0;i<len;i++)cnt[k1[i]=s[i]]++; for(int i=1;i<up;i++)cnt[i]+=cnt[i-1]; for(int i=len-1;i>=0;i--)SA[--cnt[k1[i]]]=i; for(int d=1,p=1;p<len;d<<=1,up=p){ p=0; for(int i=len-d;i<len;i++)k2[p++]=i; for(int i=0;i<len;i++)if(SA[i]-d>=0)k2[p++]=SA[i]-d; for(int i=0;i<len;i++)r[i]=k1[k2[i]]; for(int i=0;i<up;i++)cnt[i]=0; for(int i=0;i<len;i++)cnt[r[i]]++; for(int i=1;i<up;i++)cnt[i]+=cnt[i-1]; for(int i=len-1;i>=0;i--)SA[--cnt[r[i]]]=k2[i]; Swap(k1,k2); k1[SA[0]]=0; p=1; for(int i=1;i<len;i++){ k1[SA[i]]= cmp(k2,SA[i-1],SA[i],d) ? p-1 : p++; } } } void get_height(int s[],int len){ for(int i=1;i<=len;i++)Rank[SA[i]]=i; for(int i=0,p=0;i<len;i++){ int j=SA[Rank[i]-1]; while(s[p+i]==s[p+j])p++; height[Rank[i]]=p; if(p)p--; } } ll solve(int lenab,int lenb,int n,int up){ ll sumab=0,sumb=0; build_SA(ss,lenab+1,up); get_height(ss,lenab); for(int i=1;i<=lenab;i++){ if(in[SA[i]]<0)continue; sumab+=(len[in[SA[i]]]-SA[i]-height[i]); } ss[lenb]=0; build_SA(ss,lenb+1,up); get_height(ss,lenb); for(int i=1;i<=lenb;i++){ if(in[SA[i]]<0)continue; sumb+=(len[in[SA[i]]]-SA[i]-height[i]); } return sumab-sumb; } int main(){ int T,n,lenab,lenb,up; scanf("%d",&T); for(int cas=1;cas<=T;cas++){ scanf("%d",&n); lenab=lenb=0; up=30; scanf("%s",str); n++; for(int i=1;i<n;i++){ scanf("%s",s2); for(int j=0;s2[j];j++){ in[lenb]=i; ss[lenb++]=s2[j]-'a'+1; } in[lenb]=-1; len[i]=lenb; ss[lenb++]=++up; } lenab=lenb; for(int i=0;str[i];i++){ in[lenab]=n; ss[lenab++]=str[i]-'a'+1; } in[lenab]=-1; len[n]=lenab; ss[lenab]=0; ++up; ll ans=solve(lenab,lenb,n,up); printf("Case %d: %I64d\n",cas,ans); } return 0; } /** 1 0 aaaa */