hdu 3518 ( 后缀数组 至少出现两次的不重叠子串个数)
来源:互联网 发布:qstring转char数组 编辑:程序博客网 时间:2024/06/06 04:49
题意 : 一个字符串,找出这个字符串中至少出现两次的子串个数。( 至少出现两次指不能出现重叠 )
思路 : 因为字符串的长度只有1000,所以O( n * n ) 暴力统计也吃得消。做法是枚举子串的长度L ,然后根据这个L给height数组分组统计就可以了。
#include <stdio.h> #include <string.h>#include <string>#include <vector>#include <iostream>#include <algorithm> using namespace std; #define maxn 1005int wa[maxn],wb[maxn],wv[maxn],wt[maxn]; typedef long long LL ;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 *sa,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) wt[i]=0; for(i=0;i<n;i++) wt[x[i]=r[i]]++; for(i=1;i<m;i++) wt[i]+=wt[i-1]; for(i=n-1;i>=0;i--) sa[--wt[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++) wt[i]=0; for(i=0;i<n;i++) wt[wv[i]]++; for(i=1;i<m;i++) wt[i]+=wt[i-1]; for(i=n-1;i>=0;i--) sa[--wt[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++; } } int Rank[maxn],height[maxn]; void calheight(int *r,int *sa,int n){ int i , j , k = 0 ; for( i=1 ; i<=n ; i++ ) Rank[sa[i]]=i; for(i=0;i<n;i++) { if(k)k--; int j = sa[Rank[i]-1]; while(r[i+k]==r[j+k]) k++ ; height[Rank[i]] = k ; } return; } int r[maxn] , sa[maxn] ; char str[maxn] ;int main(){while( scanf( "%s" , str ) != EOF ) {if( strcmp( str , "#" ) == 0 ) break;int ans = 0 ;int len = strlen( str ) ;for( int i = 0 ; i < len ; i ++ ) r[i] = str[i] ; r[len] = 0 ;da( r , sa , len + 1 , 200 ) ;calheight( r , sa , len ) ;for( int L = 1 ; L <= len / 2 ; L ++ ) {int Max = sa[1] ;int Min = sa[1] ;for( int i = 2 ; i <= len ; i ++ ) {if( height[i] < L ) {if( Max - Min >= L ) ans ++ ;Max = Min = sa[i] ;}Max = max( Max , sa[i] ) ;Min = min( Min , sa[i] ) ;}if( Max - Min >= L ) ans ++ ;}printf( "%d\n" , ans ) ;}return 0 ;}
0 0
- hdu 3518 ( 后缀数组 至少出现两次的不重叠子串个数)
- HDU 3518 Boring counting(后缀数组啊 求字符串中不重叠的重复出现至少两次的子串的个数)
- spoj220 每个字符串至少出现两次且不重叠的最长子串(后缀数组)
- 后缀数组(每个字符串至少出现两次且不重叠的最长子串)spoj220
- spoj 220 Relevant Phrases of Annihilation (后缀数组 每个串中都至少出现两次的不重叠最长子串)
- spoj 220. Relevant Phrases of Annihilation( 后缀数组 每个字符串至少出现两次且不重叠的最长子串)
- SPOJ 220后缀数组:求每个字符串至少出现两次且不重叠的最长子串
- spoj 220 每个字符串至少出现两次且不重叠的最长子串 (后缀数组)
- HDU 3518 Boring counting 重复出现不重叠子串个数(后缀数组)
- 后缀数组(出现两次的子串且不重叠)hdu3518
- HDU 3518 Boring counting(后缀数组 所有不重叠字串出现两次以上的次数)
- hdu3518(后缀数组求至少出现两次以上的不可重叠串)
- hdu 4080 Stammering Aliens ( 后缀数组 求最长的至少出现m次可重叠子串)
- spoj220求至少出现两次且不重叠的最长公共子串
- SPOJ PHRASES 每个字符串至少出现两次且不重叠的最长子串
- HDU 6194 String String String 后缀数组 正好出现K次的子串个数 CSU1632 至少出现2次的子串个数
- ACdream 1430 SETI 后缀自动机/后缀数组 不重叠子串的个数
- SPOJ 220 Relevant Phrases of Annihilation(每个字符串至少出现两次且不重叠的最长子串)
- 黑马程序员————IO技术小结(第三篇)
- perl函数说明(fcntl)
- hibernate注解
- 格雷厄姆《聪明的投资者》学习笔记
- Redis安装方法(小白专用)
- hdu 3518 ( 后缀数组 至少出现两次的不重叠子串个数)
- 【hoj】1196 Power Crisis( Joseph'problem 变型)、1441 Eeny Meeny Moo
- Android Studio的Gradle错误解决方法
- ubi工具使用命令
- idangerous.swiper.js
- 函数说明(fileno)
- linux i2c_driver 结构体解析
- mysql中case when then 的使用
- android中style属性值介绍