当前位置: 代码迷 >> 编程 >> Codeforces Round #166 (Div. 二) D - Good Substrings
  详细解决方案

Codeforces Round #166 (Div. 二) D - Good Substrings

热度:3132   发布时间:2013-02-26 00:00:00.0
Codeforces Round #166 (Div. 2) D - Good Substrings

题意说的很清楚了,就是要寻找满足某一条件的不同字串个数。

方法一:

寻找不同字串个数体型很直接的一种方法就是把字符串hash值保存在set或者数组中,统计其中不同的个数。

//一个长为n的字符串的字串个数为n*(n+1)/2#include<cstdio>#include<cstring>#include<vector>#include<algorithm>#include<set>#define multiple 1000000007   //这里multiple如果选的太小(31,37,41)效果不如大点(131,1000000003,1000000007)好using namespace std;int main(){    int i,j;    int n,k;    char str[2000],str1[50];    int sum[2000];    memset(sum,0,sizeof(sum));    scanf("%s",str);    scanf("%s",str1);    scanf("%d",&k);    for(i=1;i<=strlen(str);i++){        sum[i]=sum[i-1]+(str1[str[i-1]-'a']=='0');    }    long long h[1500*1500];    int pos=0;    for(i=1;i<=strlen(str);i++){        long long tem=0;        for(j=i;j<=strlen(str);j++){            if(sum[j]-sum[i-1]>k)break;            tem=tem*multiple+str[j-1];            h[pos++]=tem;        }    }    sort(h,h+pos);    printf("%d\n",unique(h,h+pos)-h);}


方法二:

如果直接用set存放所有的hash值,再统计大小则会超时,解决办法是,只把长度不同的字符串的hash值放到不同的set中统计则会快很多。

//一个长为n的字符串的字串个数为n*(n+1)/2//strlen卡了我十倍的时间,一定要预处理#include<cstdio>#include<cstring>#include<vector>#include<algorithm>#include<set>#define multiple 1000000007   //这里multiple如果选的太小(31,37,41)效果不如大点(131,1000000003,1000000007)好typedef long long ll;using namespace std;int main(){    int i,j;    int n,k;    char str[2000],str1[50];    int sum[2000];    memset(sum,0,sizeof(sum));    scanf("%s",str);    scanf("%s",str1);    scanf("%d",&k);    n=strlen(str);    for(i=1;i<=n;i++){        sum[i]=sum[i-1]+(str1[str[i-1]-'a']=='0');    }    int ans=0;    //ll s[2000];    //int pos=0;    set<ll>s;    ll head=0,tem=0,last=1;    for(i=1;i<=n;i++){        s.clear();        //pos=0;        head=head*multiple+str[i-1];        if(sum[i]-sum[0]<=k){            s.insert(head);            //s[pos++]=head;        }        tem=head;        for(j=2;j+i-1<=n;j++){            tem=(tem-str[j-2]*last)*multiple+str[j+i-2];            if(sum[i+j-1]-sum[j-1]>k)continue;            s.insert(tem);            //s[pos++]=tem;        }        //sort(s,s+pos);        //ans+=unique(s,s+pos)-s;        ans+=s.size();        last*=multiple;    }    printf("%d\n",ans);}

方法三:用trie图统计字串

#include<cstdio>#include<cstring>#include<queue>#define MAXN 2000#define ALP 26typedef long long ll;using namespace std;int n,k;char s[2000];int next[MAXN*MAXN][ALP],pos;int sum[2000];int ans;int newnode(){    for(int i=0;i<ALP;i++)next[pos][i]=0;    return pos++;}void insert(char *s,int start){    int p=0;    for(int i=0;s[i];i++){        if(sum[start+i+1]-sum[start]>k)break;        int k=s[i]-'a',&x=next[p][k];        if(x==0){            x=newnode();            p=x;            ans++;        }        else            p=x;    }}int main(){    int i,j;    char str[50];    pos=0,newnode();    memset(sum,0,sizeof(sum));    scanf("%s",s);    scanf("%s",str);    scanf("%d",&k);    n=strlen(s);    for(i=1;i<=n;i++){        sum[i]=sum[i-1]+(str[s[i-1]-'a']=='0');    }    ans=0;    for(int i=0;i<n;i++){        insert(s+i,i);    }    printf("%d\n",ans);    return 0;}



方法四:用后缀数组统计子串

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 2010char r[MAXN];int sa[MAXN];int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];int height[MAXN],rank[MAXN];int sum[2000],k;inline bool cmp(int *r,int a,int b,int len){    return r[a]==r[b]&&r[a+len]==r[b+len];}void 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=p=1;p<n;j<<=1,m=p){        for(p=0,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++)            ws[i]=0;        for(i=0;i<n;i++)            ws[wv[i]=x[y[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,x[sa[0]]=0,p=i=1;i<n;i++)            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;    }}void Height(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++);}void solve(int n){    int i,j;    int ans=0;    for(i=1;i<=n;i++){        for(j=sa[i]+height[i];j<n;j++){            if(sum[j+1]-sum[sa[i]]>k)break;            ans++;        }    }    printf("%d\n",ans);}int main(){    int i,j,n;    char str[50];    memset(sum,0,sizeof(sum));    scanf("%s",r);    scanf("%s",str);    scanf("%d",&k);    n=strlen(r);    for(i=1;i<=n;i++){        sum[i]=sum[i-1]+(str[r[i-1]-'a']=='0');    }    memset(height,0,sizeof(height));    SA(n+1,130);    Height(n);    solve(n);}



  相关解决方案