SPOJ 694 Distinct Substrings
来源:互联网 发布:ubuntu怎么挂载u盘 编辑:程序博客网 时间:2024/05/19 19:31
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 694 Distinct Substrings
- SPOJ-694-Distinct Substrings
- SPOJ 694 Distinct Substrings
- SPOJ 694 Distinct Substrings
- SPOJ 694 Distinct Substrings
- spoj 694 Distinct Substrings 705 New Distinct Substrings
- spoj 694 705. New Distinct Substrings
- SPOJ 694 Distinct Substrings(后缀数组)
- 【后缀数组】【spoj 694】Distinct Substrings
- SPOJ 694 DISUBSTR Distinct Substrings 后缀数组
- spoj 694 Distinct Substrings (后缀数组应用)
- spoj 694 Distinct Substrings(后缀数组)
- spoj 694 Distinct Substrings (后缀数组)
- SPOJ 694 Distinct Substrings 后缀数组 模板
- SPOJ 694 Distinct Substrings(后缀数组)
- spoj 694 Distinct Substrings 后缀数组
- SPOJ 694 Distinct Substrings 后缀数组
- Spoj 694 Distinct Substrings(后缀数组)
- RMQ问题之Sparse_Table算法
- Skype 协议分析(2006版)
- WM_DESTROY ,WM_CLOSE,WM_QUIT
- Java 日期整理
- 归并排序
- SPOJ 694 Distinct Substrings
- Win7下安装VC6.0(转)
- Linux驱动开发学习的一些必要步骤
- 强制转换const 引用
- C/C++拾遗——main函数
- css之自动换行
- 汉诺塔算法
- 简单应用定时器和监听器
- 字符编码笔记:ASCII,Unicode和UTF-8