string string string HDU

来源:互联网 发布:宝贝标题优化工具 编辑:程序博客网 时间:2024/05/16 10:25
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k
times as an important string, and you need to find out how many substrings which are important strings.
Input
The first line contains an integer T (T100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k1) which is described above;
the second line contain a string s (length(s)105).
It's guaranteed that length(s)2106
.
Output
For each test case, print the number of the important substrings in a line.
Sample Input
22abcabc3abcabcabcabc
Sample Output
69


题意:给你一个数字k,给你一个串,让你求出有多少子串是恰好出现k次的。

思路:后缀数组啊,按照sa【i】的顺序排列一下,然后框定一长度为k的区间,求height数组在这段区间的最小值,最小值一定是满足部分条件的,如果这个长度为k的区间上面的字符串或者下面的字符串有重复,那么需要减去他们之间的最大值。这就是一个区间的贡献。但是注意当k为1的时候单独讨论一下。

#include<iostream>#include<algorithm>#include<cstdlib>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<complex>#include<queue>using namespace std;const int MAXN=1e5+10;char s[MAXN];int t1[MAXN],t2[MAXN],cc[MAXN],x[MAXN],sa[MAXN],Rank[MAXN],height[MAXN],Min[MAXN][50],kkk;int len;bool cmp(int *y,int a,int b,int k){    int a1=y[a];    int b1=y[b];    int a2=a+k>=len ? -1:y[a+k];    int b2=b+k>=len ? -1:y[b+k];    return a1==b1 && a2==b2;}int make_sa(){    int *x=t1,*y=t2;    int m=26;    for(int i=0; i<m; i++) cc[i]=0;    for(int i=0; i<len; i++) ++cc[x[i]=s[i]-'a'];    for(int i=1; i<m; i++) cc[i]+=cc[i-1];    for(int i=len-1; i>=0; i--) sa[--cc[x[i]]]=i;    for(int k=1; k<=len; k<<=1)    {        int p=0;        for(int i=len-k; i<len; i++) y[p++]=i;        for(int i=0; i<len; i++)            if( sa[i]>=k ) y[p++]=sa[i]-k;        for(int i=0; i<m; i++) cc[i]=0;        for(int i=0; i<len; i++) ++cc[x[y[i]]];        for(int i=1; i<m; i++) cc[i]+=cc[i-1];        for(int i=len-1; i>=0; i--) sa[--cc[x[y[i]]]]=y[i];        swap(x,y);        m=1;        x[sa[0]]=0;        for(int i=1; i<len; i++)            x[sa[i]]=cmp(y,sa[i],sa[i-1],k) ? m-1:m++;        if( m>=len ) break;    }}void make_height(){    for(int i=0; i<len; i++) Rank[sa[i]]=i;    height[0]=0;    int k=0;    for(int i=0; i<len; i++)    {        if(!Rank[i]) continue;        int j=sa[Rank[i]-1];        if(k) k--;        while(s[i+k]==s[j+k]) k++;        height[Rank[i]]=k;    }}void RMQ(){    for(int i=0; i<len; i++)        Min[i][0]=height[i];    for(int j=1; j<31; j++)        for(int i=0; i<len; i++)        {            if(i+(1<<j)-1<len)            {                Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);            }        }}int query(int st,int en){    int kk=(int)((log(en-st+1))/log(2.0));    return min(Min[st][kk],Min[en-(1<<kk)+1][kk]);}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d %s",&kkk,s);        len=strlen(s);        make_sa();        make_height();        long long sum=0;        RMQ();        height[len]=0;        for(int i=kkk-1; i<len; i++)        {            int x=((i-kkk+2<=i)?query(i-kkk+2,i):(len-sa[i]))-max(height[i+1],height[i-kkk+1]);            if(x>0)                sum+=x;        }        printf("%lld\n",sum);    }}



原创粉丝点击