poj 3693/hdu 2459 Maximum repetition substring spoj 687. Repeats ( 后缀数组 重复次数最多的连续重复子串)
来源:互联网 发布:淘宝网男士小包 编辑:程序博客网 时间:2024/04/29 19:05
题意 : 给定一个字符串,求重复次数最多的连续重复子串。POJ 3693 还要求输出字典序最小的重复次数最多的连续重复子串。
思路 : 论文中的方法太好了...想了半天都没点思路 ... 看了论文中的解法才有点想法.
首先我们要枚举长度L , 然后求长度为L的子串最多能连续出现多少次。首先连续出现1 次是肯定可以的,所以这里只考虑至少 2 次的情况。假设在原字符串中连续出现 2 次,记这个子字符串为 S,那么 S 肯定包括了字符 r[0], r[L], r[L*2],r[L*3], ……中的某相邻的两个。所以只须看字符 r[L*i]和 r[L*(i+1)]往前和往后各能匹配到多远,记这个总长度为 K,那么这里连续出现了 K/L+1 次。最后看最大值是多少。
穷举长度 L 的时间是 n,每次计算的时间是 n/L。所以整个做法的时间复杂度是 O(n/1+n/2+n/3+……+n/n)=O(nlogn)
其中两个位置的往后匹配只要求原字符串的LCP,往前匹配,我的做法是将原字符串反过来之后贴在原字符串之后,在sa求LCP
POJ 3693 还需要求最小字典序 。我的做法是从第一个匹配的字符开始枚举,即从第一个位置开始匹配,求得的LCP为K,然后我们往后枚举起始点,那么这个LCP就会一步步减少,直到 LCP/L-1 小于原来的值位置,那么取这里面的最小字典序解,才能用来更新答案。
下面是POJ 3693 的代码 :
#include <stdio.h>#include <string.h>//#include <string>#include <algorithm>//#include <iostream>using namespace std;#define maxn 200005#define maxm 200005int wa[maxn],wb[maxn],wv[maxn],wt[maxn];int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}void da(char *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++; } return;}int Rank[maxn],height[maxn];void calheight(char *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;height[Rank[i++]]=k) for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++); return;}int RMQ[maxn];int mm[maxn];int best[20][maxn];void initRMQ(int n){ int i,j,a,b; for(int i=1;i<=n;i++)RMQ[i] = height[i] ; for(mm[0]=-1,i=1;i<=n;i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; for(i=1;i<=n;i++) best[0][i]=i; for(i=1;i<=mm[n];i++) for(j=1;j<=n+1-(1<<i);j++) { a=best[i-1][j]; b=best[i-1][j+(1<<(i-1))]; if(RMQ[a]<RMQ[b]) best[i][j]=a; else best[i][j]=b; } return;}int askRMQ(int a,int b){ int t; t=mm[b-a+1];b-=(1<<t)-1; a=best[t][a];b=best[t][b]; return RMQ[a]<RMQ[b]?a:b;}int lcp(int a,int b){ int t; a=Rank[a];b=Rank[b]; if(a>b) {t=a;a=b;b=t;} return(height[askRMQ(a+1,b)]);}char str[maxn] , str2[maxn] ;int sa[maxn] ;char ans[maxn] , tmp[maxn] ;int main(){int casn = 1 ;while( scanf( "%s" , str ) != EOF ) {if( strcmp( str , "#" ) == 0 ) break;ans[0] = 254 ;ans[1] = 0 ; strcpy( str2 , str ) ; //strrev( str2 ) ;int Len ; int len = Len = strlen( str ) ; str[len] = '$' ; str[len+1] = 0 ; //strcat( str , str2 ) ; for( int i = 0 ; i < len ;i ++ ) { str[len+i+1] = str2[len-i-1] ; } str[len+len+1] = 0 ; len = strlen( str ) ; // 最后再加一个之前没有出现过的字符 , 避免了判断边界情况 str[len] = '&' ; str[len+1] = 0 ; len ++ ; da( str , sa , len + 1 , 200 ) ; calheight( str , sa , len ) ; initRMQ( len ) ; len -- ;// 枚举 Lint Max = 0 ;for( int L = 1 ; L <= Len ; L ++ ) {for( int i = 0 ; ( i + 1 ) * L < Len ; i ++ ) {int K1 = lcp( i * L , ( i + 1 ) * L ) ;int K2 = lcp( len - i * L - 1 , len - ( i + 1 ) * L - 1 ) ;int K = K1 + K2 ;if( K > 0 ) K -- ;int s = i * L - K2 + 1 ;int cnt = K / L + 1 ;if( cnt >= Max ) {//tmp = string( str+s , str + s + cnt * L ) ;if( cnt > Max ) { Max = cnt ; ans[0] = 254 ; ans[1] = 0 ; }int j = 0 ;for( int i = s ; i < s + cnt * L ; i ++ ) {tmp[j++] = str[i] ;}tmp[j] = 0 ;if( strcmp( ans, tmp ) > 0 ) {strcpy( ans , tmp ) ;}int i = 1 ;while( ( K - i ) / L + 1 == cnt ) {tmp[j++] = str[s + cnt * L + i -1] ;tmp[j] = 0 ;if( strcmp( ans , tmp + i ) > 0 ) {strcpy( ans , tmp + i ) ;}i ++ ;}}}}printf( "Case %d: %s\n" , casn ++ , ans ) ;}return 0 ;}// ccaaccaaccaacc
0 0
- poj 3693/hdu 2459 Maximum repetition substring spoj 687. Repeats ( 后缀数组 重复次数最多的连续重复子串)
- POJ - 3693 Maximum repetition substring(后缀数组求重复次数最多的连续重复子串)
- POJ 3693 Maximum repetition substring(后缀数组[重复次数最多的连续重复子串])
- Maximum repetition substring+POj+后缀数组之求重复次数最多的连续重复子串
- Poj 3693 & Hdu 2459 Maximum repetition substring (08合肥Online 后缀数组+RMQ 重复次数最多的连续重复子串)
- poj 1743Maximum repetition substring(后缀数组+RMQ+重复次数最多的连续重复子串))
- HDU 2459 Maximum repetition substring(后缀数组+RMQ-重复次数最多的子串)
- POJ 3693 Maximum repetition substring (后缀数组+RMQ 求重复最多的连续子串)
- POJ 3693 Maximum repetition substring (后缀数组+RMQ 求重复最多的连续子串)
- SPOJ REPEATS - Repeats(后缀数组[重复次数最多的连续重复子串])
- POJ 3693 Maximum repetition substring 后缀数组求重复次数最多子串
- SPOJ 687 Repeats (后缀数组+RMQ 重复次数最多的连续重复子串)
- POJ 3693 Maximum repetition substring (求重复次数最多的连续子串,4级)
- POJ 3693 Maximum repetition substring(重复次数最多的连续子串 字典序最小)
- POJ 题目 3693 Maximum repetition substring(后缀数组+RMQ+枚举求最小字典序的重复次数最多的子串)
- Repeats SPOJ (后缀数组,寻找一个重复次数最多的子串)
- SPOJ题目687 Repeats(后缀数组+RMQ求重复次数最多的子串的重复次数)
- POJ 3693 重复次数最多的连续重复子串 后缀数组
- jQuery Js 日期格式的转换
- wifi共享精灵教你找工作
- 不可重现的BUG的应对策略
- rpmbuild命令详解
- Android Canvas绘图详解(图文)
- poj 3693/hdu 2459 Maximum repetition substring spoj 687. Repeats ( 后缀数组 重复次数最多的连续重复子串)
- Xpath—解决问题的良药
- 前端学习书籍推荐
- 1.读取TXT文本内容
- app设计原则
- Windows中获取MAC地址的几种方法 (转)
- Linux下的一些I/O统计工具
- 使用JSONP ajax获取不同源的数据
- VC++ 获取网卡IP、DNS、适配器名称