3 2 abab ab ba 1 aaa bbb 2 aaaa aa aaa
Case 1: 3 Case 2: 3 Case 3: 1
题意:一个字符串,给定若干病毒串,求不包含病毒串的字串个数。
把病毒串添加在字符串后面,中间用不同的字符隔开,然后求一个sa,height,然后从后向前扫,
去掉的包含两个部分,一个是字符串本身已经出现过的,另外一个是包含病毒串的,
代码:
/* *********************************************** Author :rabbit Created Time :2014/4/10 16:33:22 File Name :A.cpp ************************************************ */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <string> #include <time.h> #include <math.h> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) typedef long long ll; const int maxn=500200; int t1[maxn],t2[maxn],c[maxn]; bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int str[],int sa[],int rank[],int height[],int n,int m){ n++; int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=str[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1){ 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<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; if(p>=n)break; m=p; } int k=0;n--; for(i=0;i<=n;i++)rank[sa[i]]=i; for(i=0;i<n;i++){ if(k)k--; j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; } } int rank[maxn],height[maxn],r[maxn],sa[maxn]; char str[maxn]; int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int T; scanf("%d",&T); for(int t=1;t<=T;t++){ int len,len1,n; scanf("%d",&n); scanf("%s",str); len=len1=strlen(str); for(int i=0;i<len;i++)r[i]=str[i]; r[len++]=127; while(n--){ scanf("%s",str); int cnt=strlen(str); for(int i=0;i<cnt;i++) r[len++]=str[i]; r[len++]=‘#‘; } r[len]=0; da(r,sa,rank,height,len,200); ll ans=0;int lcp=0; for(int i=1;i<=len;i++){ if(sa[i]>len1)lcp=height[i]; else{ ans+=len1-sa[i]-max(height[i],lcp); lcp=min(lcp,height[i]); } } printf("Case %d: %I64d\n",t,ans); } return 0; }
原文:http://blog.csdn.net/xianxingwuguan1/article/details/23369141