SPOJ 694 Distinct Substrings

原创 2012年03月24日 10:16:25

http://www.spoj.pl/problems/DISUBSTR/

题意:给定一个字符串,len<=1000,求不同子串的个数。

思路: 后缀数组。 每个子串一定是某后缀前缀,于是原问题就可以转换为求所有后缀中不同前缀的个数,后缀的排列顺序为字典序排序suffix(sa[1]) < suffix(sa[2] ) < suffix(sa[3])  ....  ,由后缀的排列顺序我们可以得出,由后缀suffix(sa[k]) 产生的新前缀的个数为:len - sa[k] - height[k] ,因为此时suffix(sa[k]) 与 suffix(sa[k-1]) 共有height[k]个前缀是相同的。这样在用O(NlogN)的复杂度求出sa[]数组和 O(N)的复杂度求出height[] 数组之后就可以在O(N)的时间内求出答案。总的复杂度为:O(NlogN)。

代码:

#include<stdio.h>
#include<string.h>
#define MAXN 2010 
char ch[MAXN] ;
int num[MAXN] ;
int T;
int sa[MAXN] , rank[MAXN] ,height[MAXN] ;  
int wa[MAXN] , wb[MAXN] ,wv[MAXN],wd[MAXN] ;   
int N,M;  
int cmp(int *r , int a , int b , int l){  
    return r[a] == r[b] && r[a+l] == r[b+l] ;     
}  
void DA(int *r,int n,int m){        //O(NlogN)  
    int i, j , p , *x=wa, *y=wb,*t ;  
    for( i = 0 ; i < m ; i++ )   wd[i] = 0 ;  
    for( i = 0 ; i < n ; i++ )       wd[x[i]=r[i]] ++ ;  
    for( i = 1 ; i < m ; i++ )       wd[i] += wd[i-1] ;  
    for( i = n-1 ;i >= 0 ; i-- )     sa[--wd[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 < n ; i++)    wv[i] = x[y[i]] ;  
        for( i = 0 ; i < m ; i++)    wd[i] = 0 ;  
        for( i = 0 ; i < n ; i++)    wd[wv[i]] ++ ;  
        for( i = 1 ; i < m ; i++)    wd[i] += wd[i-1] ;  
        for( i = n-1 ; i >= 0 ; i--) sa[ --wd[wv[i]]] = y[i] ;  
        for( t = x , x = y , y = t , p = 1 , x[ sa[0] ] = 0,i = 1;i < n ; i++){  
            x[sa[i]] = cmp( y ,sa[i-1] ,sa[i] , j ) ? p-1: p++;   
        }     
    }  
}   
  
void calHeight(int *r , int n){  
    int i , j , k = 0 ;  
    for( i = 1 ; i <= n ; i++)   rank[sa[i]] = i ;  
    for( i = 0 ; i < n ; height[ rank[i++]]=k){  
        for( k ? k-- : 0 , j=sa[rank[i]-1]; r[i+k]==r[j+k] ; k++) ;   
    }     
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%s",ch);	
		int len = strlen(ch);
		for(int i=0;i<len;i++){
			num[i] = ch[i] ;	
		}
		num[len] = 0 ;
		DA(num, len+1 , 300);
		calHeight(num,len);
		int ans = len - sa[1] ;
		for(int i=2;i<=len;i++){
			ans += len - sa[i] - height[i] ;
		}
		printf("%d\n",ans);
	}		
	return 0 ;	
}


SPOJ - DISUBSTR Distinct Substrings(后缀数组求不相同的子串个数)

Description Given a string, we need to find the total number of its distinct substrings. Input ...
  • u011345136
  • u011345136
  • 2014年09月26日 19:03
  • 1140

spoj 694 求一个字符串中不同子串的个数

SPOJ Problem Set (classical) 694. Distinct Substrings Problem code: DISUBSTR Gi...
  • u011026968
  • u011026968
  • 2014年07月02日 15:09
  • 2202

SPOJ 694 求不同子串数 后缀数组

题目链接:http://www.spoj.com/problems/DISUBSTR/ 题意: T个测试数据 每个测试数据一行:字符串,求该字符串有多少个不同的子串。   论文思路: 每个...
  • qq574857122
  • qq574857122
  • 2014年01月22日 10:38
  • 1379

SPOJ 694. Distinct Substrings (不相同的子串的个数--后缀数组)

题意:给定一个字符串,求不相同的子串的个数。 思路:子串的总个数是n*(n+1)/2 现在用height数组解决所以把子串的个数看成是以i字符串开头的子串的个数的和,那么总个数减去sum(heig...
  • kalilili
  • kalilili
  • 2015年03月18日 19:57
  • 441

SPOJ 694 Distinct Substrings(后缀数组 所有不相同子串个数)

题目链接:http://www.spoj.com/problems/DISUBSTR/ 第一次做spoj上的题目 这个题目还是利用height数组,表示后缀数组理解还是靠height数组的理解 这...
  • sunrainchy
  • sunrainchy
  • 2013年07月30日 15:36
  • 475

spoj694 Distinct Substrings(后缀数组+统计不同子串的个数)

给定一个字符串,求不相同的子串的个数。 算法分析: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相 同的前缀的个数。如果所有的后缀按照 suffix(sa[1]), suff...
  • u013167299
  • u013167299
  • 2015年09月14日 20:08
  • 343

694. Distinct Substrings SPOJ

//给你长度为n,求不同的字符串个数 //每个子串一定是某个后缀的前缀,那么原问题等价于所求后缀之间不同的前缀个数 #include #include #include using name...
  • Yukar_syt
  • Yukar_syt
  • 2012年09月06日 14:18
  • 331

SPOJ 694 DISUBSTR Distinct Substrings 后缀数组

题目大意: 对于给出的字符串(长度不超过1000) 求其不同的子串的个数 大致思路: 就是一个简单的height数组性质的利用,  如果每个子串我们用从位置j开始且长度为k来表示不同的...
  • u013738743
  • u013738743
  • 2015年02月09日 13:46
  • 407

Spoj694(Distinct Substrings)求字符串不相同的子串个数(后缀数组)

/********************************************* 题目地址: http://www.spoj.com/problems/DISUBSTR/ 题目大意: 给...
  • Jarily
  • Jarily
  • 2013年03月23日 19:55
  • 1275

spoj694 Distinct Substrings

SPOJ Problem Set (classical)694. Distinct SubstringsProblem code: DISUBSTR Given a string, we need t...
  • hqd_acm
  • hqd_acm
  • 2011年04月13日 20:32
  • 596
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SPOJ 694 Distinct Substrings
举报原因:
原因补充:

(最多只允许输入30个字)