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;
}
同的前缀的个数。如果所有的后缀按照 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;
}
相关文章推荐
- OpenGL 多重纹理
- [Android界面] 导航栏下划线出现偏移
- 集群、分布式、负载均衡区别与联系
- Ubuntu14.04+eclipse下cocos2d-x3.6正式版环境的搭建
- Android学习系列之(七)Fragment深入
- java入门学习总结——【java菜鸟成长记】
- XCode单元测试
- Ubuntu下搭建Cocos2D-X 3.6开发环境
- 【机器学习基础】理解为什么机器可以学习——Hoeffding不等式
- 集群化部署定时任务apscheduler库 - 推酷
- 对于问题,要打破砂锅问到底,也要懂得不求甚解——不执着于问题本身
- CSSborder制作小三角形
- 验证码
- Volley框架全解析
- js 判断所选时间(或者当前时间)是否在某一时间段的实现代码
- UC/OS II 任务管理(6)之多任务启动
- Missing styles. Is the correct theme chosen for this layout?
- Week1-1Dynamic Connectivity
- 关于GIT的一些注意点
- CentOS 7 通过 持续集成包 安装最新的 Mono