LOJ 1428 Melody Comparison(後綴數組)

1428 - Melody Comparison
Time Limit: 4 second(s) Memory Limit: 64 MB

Bono, a very famous singer, had always wanted to have a machine to turn the melodies into strings. Last month he earned two million dollars and bought one of those amazing machines, suddenly he began to play some solos to test his new toy. Surprisingly this machine was able to take a piece of song and output a string of lowercase characters from 'a' to 'z'. After playing his two best solos he took the resulting strings A and B and began to count substrings and repetitions. He is a great singer but is not good in programming at all, that's why he needs you to help him to find how many distinct substrings of A that don't contain B as a substring.

Input

Input starts with an integer T (≤ 25), denoting the number of test cases.

Each case starts with a line containing string A. The next line contains string B. You can safely assume that the strings are non-empty and none of their length is more than 50000 and they will contain lowercase English alphabets only.

Output

For each case, print the case number and the number of substrings that Bono needs to know.

Sample Input

Output for Sample Input

4

ababa

ba

ababa

a

abbabaaaba

aa

ababababa

bab

Case 1: 3

Case 2: 1

Case 3: 15

Case 4: 5

 


Problem Setter: Jose Luis Castrillon Garrido
Special Thanks: Jane Alam Jan 

題意:求a串的子串中不包含b串的個數
題解:先用KMP預處理出每個段可以到最長的有效長度,然後用後綴數組就能解決

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define MAXN 50008
char s1[MAXN],s2[MAXN];
int nex[MAXN],lon;
int num[MAXN];

int r[MAXN],pre[MAXN];
int bucket[MAXN];
int rankx[MAXN],ranky[MAXN];
int sa[MAXN],height[MAXN];

int MIN(int x,int y){ return x<y?x:y; }
void get_next(char *s)
{
    int i,j;
    nex[0]=j=-1;
    for(i=0;s[i];)
    {
        if(j==-1||s[i]==s[j]) nex[++i]=++j;
        else j=nex[j];
    }
}
void mycount()
{
    int i,k,j=0,now=0;
    int len1=strlen(s1),len2=strlen(s2);

    for(i=0;i<len1;i++) num[i]=len1-i;
    for(i=0;s1[i];)
    {
        if(j==-1||s1[i]==s2[j]) j++,i++;
        else j=nex[j];
        if(j==len2)
        {
            j=nex[j];
            for(k=now;k<=i-len2;k++) num[k]=i-1-k;
            now=i-len2+1;
        }
    }
}
int cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void suffix_array(int *s,int *sa,int n,int m)
{
    int i,j,p,*x=rankx,*y=ranky,*t;

    for(i=0;i<m;i++) bucket[i]=0;
    for(i=0;i<n;i++) bucket[x[i]=s[i]]++;
    for(i=1;i<m;i++) bucket[i]+=bucket[i-1];
    for(i=n-1;i>=0;i--) sa[--bucket[x[i]]]=i;

    for(j=1,p=1;p<n;j*=2,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++) bucket[i]=0;
        for(i=0;i<n;i++) bucket[x[y[i]]]++;
        for(i=1;i<m;i++) bucket[i]+=bucket[i-1];
        for(i=n-1;i>=0;i--) sa[--bucket[x[y[i]]]]=y[i];

        t=x,x=y,y=t;
        for(p=i=1,x[sa[0]]=0;i<n;i++)
        x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
}
void calculate_height(int *r,int *sa,int *x,int *height,int n)
{
    int i,j,k=0;

    for(i=0;i<=n;i++) x[sa[i]]=i;
    for(i=0;i<n;height[x[i++]]=k)
    {
        for(k?k--:0,j=sa[x[i]-1];r[i+k]==r[j+k];k++);
    }
}
int solve()
{
    int i,res=0;
    for(i=1;i<=lon;i++)
    {
        res+=num[sa[i]]-MIN(num[sa[i]],height[i]);
    }
    return res;
}
int main()
{
    int t,i,cas=1;

    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",s1,s2);
        lon=strlen(s1);

        get_next(s2);
        mycount();
        for(i=0;i<lon;i++) r[i]=s1[i]-'a'+1;
        r[i]=0;
        suffix_array(r,sa,lon+1,30);
        calculate_height(r,sa,rankx,height,lon);
        printf("Case %d: %d\n",cas++,solve());
    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章