POJ 2406
来源:互联网 发布:64位版本的windows 编辑:程序博客网 时间:2024/05/29 19:12
题目链接:http://poj.org/problem?id=2406
题意: 字符串a是由字符串b重复k次得到的,求k的最大值
从小到大枚举字符串b的长度i,当LCP(rank[i],rank[0])==n-i时,就证明a可以由b重复n/i次得到,想象一下
所以我们只要求出所有rank[i]到rank[0]之间的最小值即刻,用RMQ全部预处理的话会超内存
超时的倍增后缀数组
#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#define MAXN 1000005using namespace std;char s[MAXN];int d[MAXN];int sa[MAXN],t1[MAXN],t2[MAXN],c[MAXN],rank[MAXN],height[MAXN],n;void build_sa(int m){ int i,*x=t1,*y=t2; 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>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; m=p; }}void calheight(){ int j,k=0; for(int i=1;i<=n;i++) rank[sa[i]]=i; for(int i=0;i<n;height[rank[i++]]=k){ for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++); }}void LCP(){ int k=rank[0]; d[k]=n; for(int i=k-1;i>=0;i--){ if(d[i+1]<height[i+1]) d[i]=d[i+1]; else d[i]=height[i+1]; } for(int i=k+1;i<=n;i++){ if(d[i-1]<height[i]) d[i]=d[i-1]; else d[i]=height[i]; }}int solve(){ for(int i=1;i<=n/2;i++){ if(n%i) continue; if(d[rank[i]]==n-i) return n/i; } return 1;}int main(){ while(~scanf("%s",s)){ n=strlen(s); if(s[0]=='.'&&n==1) break; s[n]=0; n++; build_sa(128); n--; calheight(); LCP(); int ans=solve(); printf("%d\n",ans); } return 0;}
DC3 算法 AC代码
#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#define MAXN 1000005#define F(x) ((x)/3+((x)%3==1?0:tb))#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)using namespace std;int ss[MAXN*3];char s[MAXN];int d[MAXN];int sa[MAXN*3],rank[MAXN],height[MAXN];int wa[MAXN],wb[MAXN],wv[MAXN],wss[MAXN];int c0(int *r,int a,int b){ return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];}int c12(int k,int *r,int a,int b){ if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1); else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];}void sort(int *r,int *a,int *b,int n,int m){ int i; for(i=0;i<n;i++) wv[i]=r[a[i]]; for(i=0;i<m;i++) wss[i]=0; for(i=0;i<n;i++) wss[wv[i]]++; for(i=1;i<m;i++) wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--) b[--wss[wv[i]]]=a[i]; return;}void dc3(int *r,int *sa,int n,int m){ int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p; r[n]=r[n+1]=0; for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i; sort(r+2,wa,wb,tbc,m); sort(r+1,wb,wa,tbc,m); sort(r,wa,wb,tbc,m); for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++) rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++; if(p<tbc) dc3(rn,san,tbc,p); else for(i=0;i<tbc;i++) san[rn[i]]=i; for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3; if(n%3==1) wb[ta++]=n-1; sort(r,wb,wa,ta,m); for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i; for(i=0,j=0,p=0;i<ta && j<tbc;p++) sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++]; for(;i<ta;p++) sa[p]=wa[i++]; for(;j<tbc;p++) sa[p]=wb[j++]; return;}void calheight(int n){ int j,k=0; for(int i=1;i<=n;i++) rank[sa[i]]=i; for(int i=0;i<n;height[rank[i++]]=k){ for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++); }}void LCP(int n){ int k=rank[0]; d[k]=n; for(int i=k-1;i>=0;i--){ if(d[i+1]<height[i+1]) d[i]=d[i+1]; else d[i]=height[i+1]; } for(int i=k+1;i<=n;i++){ if(d[i-1]<height[i]) d[i]=d[i-1]; else d[i]=height[i]; }}int solve(int n){ for(int i=1;i<=n/2;i++){ if(n%i) continue; if(d[rank[i]]==n-i) return n/i; } return 1;}int main(){ int n; while(~scanf("%s",s)){ n=strlen(s); if(s[0]=='.'&&n==1) break; for(int i=0;i<n;i++) ss[i]=s[i]+1; ss[n]=0; dc3(ss,sa,n+1,200); calheight(n); LCP(n); int ans=solve(n); printf("%d\n",ans); } return 0;}
0 0
- POJ 2406
- POJ 2406
- poj 2406
- POJ 2406
- poj 2406
- poj 2406
- poj 2406
- poj 2406
- poj 2406
- poj 2406
- 【POJ 2406 】
- POJ 2406
- poj 2406
- POJ 2406
- poj 2406
- POJ-2406
- POJ 2406
- poj--2406
- svn status
- 双向结束队列的操作
- PreparedStatement 使用like
- 成员变量是属于声明的对象还是实际对象
- 求和号
- POJ 2406
- Linux下动态共享库加载时的搜索路径详解
- Red and Black
- Android编程之SparseArray<E>详解
- 推荐几个机器学习算法及应用领域相关的中国大牛
- jquery效率优化
- context:component-scan扫描使用上的容易忽略的use-default-filters
- 蓝桥杯 算法提高 金属采集 (树形动态规划)
- A - Red and Black(3.2.1)