您的位置:首页 > 其它

spoj -705 New Distinct Substrings--后缀数组

2015-09-05 16:16 393 查看
每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相

同的前缀的个数。如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]),suffix(sa[3]), ...... ,suffix(sa
)的顺序计算,不难发现,对于每一次新加进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀。但是其中有height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”出
n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法的时间复杂度为 O(n)。 

//
// main.cpp
// spoj 705 New Distinct Substrings--后缀数组
//
// Created by XD on 15/9/5.
// Copyright (c) 2015年 XD. All rights reserved.
//

#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespace std ;
const int maxn = 50000 + 10 ;
int s[maxn] ;
int r[maxn] , t[maxn] , t1[maxn] ,height[maxn],c[maxn],sa[maxn] ;
void build_sa(int n , int m )
{
int *x =t,*y = t1 ,*temp,i ;
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>-1;i--) sa[--c[x[y[i]]]] = y[i] ;
temp =x ; x = y ;y =temp ;
p = 1 ; x[sa[0]] = 0 ;
for(i = 1; i < n ; i++)
{
x[sa[i]] = (y[sa[i]]== y[sa[i-1]] && y[sa[i] + k ]== y[sa[i-1] + k ])? p-1:p++ ;
}
if (p >= n ) {
break ;
}
m = p ;
}
}
void getHeight(int n )
{
for (int i = 0 ; i < n ; i++) {
r[sa[i]] = i ;
}
int k = 0 ;
for (int i = 0; i < n-1 ; i++) {
if(k) k-- ;
int j = sa[r[i]-1] ;
while (s[i+k] == s[j+k]) {
k++ ;
}
height[r[i]] = k ;
}
}

int main(int argc, const char * argv[]) {
int kase ; scanf("%d" ,&kase) ;
getchar() ;char t[maxn] ;
while (kase--) {
gets(t) ;
int len = (int )strlen(t) ;
for(int i = 0 ; i < len ; i++)
{
s[i] = t[i] ;
}
s[len] = 0 ;
build_sa(len + 1, 128) ;
getHeight(len+1) ;
int ans = 0;
for (int i = 1 ; i < len+1 ; i++) {
ans += (len - sa[i] - height[i]) ;
}
printf("%d\n" ,ans) ;
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: