HDU5769 Substring(后缀数组)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5769

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <algorithm>
using namespace std;
const int MAXN = 1e5+7;
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 rankk[],int height[],int n,int m)
{
    n++;
    int i, j, p, *x = t1, *y = t2;
    //第一轮基数排序,如果s的最大值很大,可改为快速排序
    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;
        //直接利用sa数组排序第二关键字
        for(i = n-j; i < n; i++)
            y[p++] = i;//后面的j个数第二关键字为空的最小
        for(i = 0; i < n; i++)
            if(sa[i] >= j)
                y[p++] = sa[i] - j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        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];
        //根据sa和x数组计算新的x数组
        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++)rankk[sa[i]] = i;
    for(i = 0; i < n; i++)
    {
        if(k)k--;
        j = sa[rankk[i]-1];
        while(str[i+k] == str[j+k])k++;
        height[rankk[i]] = k;
    }
}
int rankk[MAXN],height[MAXN];
int RMQ[MAXN];
int mm[MAXN];
int best[20][MAXN];
char str[MAXN];
int r[MAXN];
int sa[MAXN];
int len;
int hxpos[MAXN];
int xpos[MAXN];
int main()
{
    int t,cas;
    __int64 sum;
    char x[2];
    int i,n,cnt;
    scanf("%d",&t);
    for(cas=1; cas<=t; cas++)
    {
        sum=0;
        scanf("%s",x);
        scanf("%s",str);
        len=strlen(str);
        memset(xpos,-1,sizeof(xpos));
        cnt=0;
        for(i=0; i<len; i++)
        {
            if(str[i]==x[0])
                xpos[cnt++]=i;
        }
        for( i = 0; i < len; i++)r[i] = str[i]-'a'+1;
        r[len] = 0;
        da(r,sa,rankk,height,len,30);
        cnt=0;
        for(i=0; i<len; i++)
        {
            while(xpos[cnt]<i&&xpos[cnt]!=-1)
                cnt++;
            if(xpos[cnt]==-1)
                hxpos[rankk[i]]=len-i+1;
            else
                hxpos[rankk[i]]=xpos[cnt]-i+1;
        }
        for(i=0; i<len; i++)
        {
            sum+=(__int64)(len-sa[i+1]-max(height[i+1],hxpos[i+1]-1));
        }
        printf("Case #%d: %I64d\n",cas,sum);
    }
    return 0;
}

 

posted @ 2016-08-12 19:52  vwqv  阅读(247)  评论(0编辑  收藏  举报