hdu 5769 后缀数组

来源:互联网 发布:centos下安装jdk1.8 编辑:程序博客网 时间:2024/05/22 06:46
?? is practicing his program skill, and now he is given a string, he has to calculate the total number of its distinct substrings. 
But ?? thinks that is too easy, he wants to make this problem more interesting. 
?? likes a character X very much, so he wants to know the number of distinct substrings which contains at least one X. 
However, ?? is unable to solve it, please help him.
Input
The first line of the input gives the number of test cases T;T test cases follow. 
Each test case is consist of 2 lines: 
First line is a character X, and second line is a string S. 
X is a lowercase letter, and S contains lowercase letters(‘a’-‘z’) only. 

T<=30 
1<=|S|<=10^5 
The sum of |S| in all the test cases is no more than 700,000.
Output
For each test case, output one line containing “Case #x: y”(without quotes), where x is the test case number(starting from 1) and y is the answer you get for that case. 
Sample Input
2 a abc b bbb
Sample Output
Case #1: 3 Case #2: 3          
Hint
In first case, all distinct substrings containing at least one a: a, ab, abc. 

In second case, all distinct substrings containing at least one b: b, bb, bbb.

问所给串的含有所给字符的不同子串有多少个

思路:

首先预处理出每个后缀后边最近的所给字符的位置,然后对主串处理出后缀数组

那么对于后缀sa[i]来说,他对结果的贡献就是

n-max(sa[i]+height[i],f[sa[i]])

这个公式还是很容易懂得,满足两种情况

1.前边后缀已经算过的不再计算(用height数组)

2.包含所给字符

ac代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int mx=200100;char st[mx];int s[mx],sa[mx],t[mx],t2[mx],c[mx],n;int ran[mx],height[mx];void build_sa(int m){    int i,*x=t,*y=t2;    for (i=0;i<m;i++) c[i]=0;    for (i=0;i<n;i++) c[x[i]=s[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 (int k=1;k<=n;k<<=1)    {        int p=0;        for (i=n-k;i<n;i++) y[p++]=i;        for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k;        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]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;        if (p>=n) break;        m=p;    }}void getHeight(){    int i,j,k=0;    for (i=0;i<n;i++) ran[sa[i]]=i;    for (i=0;i<n;i++)    {        if (k) k--;        int j=sa[ran[i]-1];        while (s[i+k]==s[j+k]) k++;        height[ran[i]]=k;    }}char a[5];int f[mx];int main(){    int x;    scanf("%d",&x);    int cas=0;    while(x--)    {        scanf("%s%s",a,st);        int len=strlen(st);        int flag=len;        for(int i=len-1;i>=0;i--)        {            if(st[i]==a[0])            flag=i;            f[i]=flag;        }        n=len+1;        for(int i=0;i<len;i++)        s[i]=st[i]-'a'+1;        s[len]=0;        build_sa(30);        getHeight();        long long ans=(long long)len-max(sa[1],f[sa[1]]);        for(int i=2;i<=len;i++)        {            ans+=(long long)len-max(sa[i]+height[i],f[sa[i]]);        }        printf("Case #%d: %lld\n",++cas,ans);    }}


原创粉丝点击