码迷,mamicode.com
首页 > 编程语言 > 详细

HDU5769 Substring(后缀数组)

时间:2016-08-12 21:14:42      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

链接: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;
}

 

HDU5769 Substring(后缀数组)

标签:

原文地址:http://www.cnblogs.com/vwqv/p/5766197.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!