POJ 3261 Milk Patterns (离散化+后缀数组 可重叠k次最长重复子串)

Bertha 。 2021-11-16 10:06 285阅读 0赞

2014-6-23 更新

用DC3重写了此题,同时更换了height数组分组后的统计方法

原代码 4804K407MS

修改后 1048K32MS

————————————分割线——————————————

题意:给出一串长度为n的字符,再给出一个k值,要你求重复次数大于等于k次的最长子串长度

思路:首先离散化,二分答案,按照二分值k将height数组分组,对于k是否可行的判定:由height数组性质,同一组中个数大于等于k则可行。

  1. #pragma warning(disable:4786)
  2. #include <set>
  3. #include <map>
  4. #include <cstdio>
  5. #include <cstring>
  6. #include <cstdlib>
  7. #include <algorithm>
  8. #include <vector>
  9. using namespace std;
  10. #define max(a,b) ((a)>(b)?(a):(b))
  11. #define min(a,b) ((a)<(b)?(a):(b))
  12. const int N = int(2e5)+10;
  13. int cmp(int *r,int a,int b,int l){
  14. return (r[a]==r[b]) && (r[a+l]==r[b+l]);
  15. }
  16. int wa[N],wb[N],ws[N],wv[N];
  17. int rank[N],height[N];
  18. void DA(int *r,int *sa,int n,int m){
  19. int i,j,p,*x=wa,*y=wb,*t;
  20. for(i=0;i<m;i++) ws[i]=0;
  21. for(i=0;i<n;i++) ws[x[i]=r[i]]++;
  22. for(i=1;i<m;i++) ws[i]+=ws[i-1];
  23. for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
  24. for(j=1,p=1;p<n;j*=2,m=p)
  25. {
  26. for(p=0,i=n-j;i<n;i++) y[p++]=i;
  27. for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
  28. for(i=0;i<n;i++) wv[i]=x[y[i]];
  29. for(i=0;i<m;i++) ws[i]=0;
  30. for(i=0;i<n;i++) ws[wv[i]]++;
  31. for(i=1;i<m;i++) ws[i]+=ws[i-1];
  32. for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
  33. for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
  34. x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
  35. //printf("p = %d\n", p );
  36. }
  37. }
  38. void calheight(int *r,int *sa,int n){
  39. // memset(height,0,sizeof(height));
  40. // memset(rank,0,sizeof(rank));
  41. int i,j,k=0;
  42. for(i=1;i<=n;i++) rank[sa[i]]=i;
  43. for(i=0;i<n; height[rank[i++]] = k )
  44. for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
  45. }
  46. int data[N],sa[N],temp[N],n,k;
  47. map<int,int> mp;
  48. vector<int> S[N];
  49. bool Judge (int a)
  50. {
  51. int i,cur = -1;
  52. for (i=1;i<=n;i++) //分组
  53. {
  54. if (height[i] < a)
  55. S[++cur].clear();
  56. S[cur].push_back(i);
  57. }
  58. for (i=0;i<=cur;i++)
  59. if (S[i].size()>=k)
  60. return true;
  61. return false;
  62. }
  63. void Deal (int *data,int n,int m,int K)
  64. {
  65. DA(data,sa,n+1,m);
  66. calheight(data,sa,n);
  67. int low=0,high=n,mid,ans=0;
  68. while (low<high) //注意二分的写法
  69. {
  70. mid = (low+high)>>1;
  71. if ( Judge(mid) )
  72. ans=mid,low=mid+1;
  73. else high = mid;
  74. }
  75. printf("%d\n",ans);
  76. }
  77. int main ()
  78. {
  79. #ifdef ONLINE_JUDGE
  80. #else
  81. freopen("read.txt","r",stdin);
  82. #endif
  83. while (~scanf("%d%d",&n,&k))
  84. {
  85. int i;
  86. for (i=0;i<n;i++)
  87. {
  88. scanf("%d",&data[i]);
  89. temp[i]=data[i];
  90. }
  91. if (n==1 && k==1)
  92. {
  93. printf("1\n");
  94. continue;
  95. }
  96. sort(temp,temp+n);
  97. int sz = unique(temp,temp+n)-temp; //去重
  98. mp.clear();
  99. for (i=0;i<sz;i++) //离散化
  100. mp[ temp[i] ] = i+1;
  101. for (i=0;i<n;i++)
  102. data[i] = mp[ data[i] ];
  103. data[n] = 0;
  104. Deal(data,n,sz+1,k-1);
  105. }
  106. return 0;
  107. }
  108. #pragma warning(disable:4786)
  109. #include <set>
  110. #include <map>
  111. #include <cstdio>
  112. #include <cstring>
  113. #include <cstdlib>
  114. #include <algorithm>
  115. #include <vector>
  116. using namespace std;
  117. #define max(a,b) ((a)>(b)?(a):(b))
  118. #define min(a,b) ((a)<(b)?(a):(b))
  119. const int N = int(2e4)+10;
  120. #define F(x) ((x)/3+((x)%3==1?0:tb))
  121. #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
  122. int wa[N],wb[N],wv[N],ws[N];
  123. int c0 (int *r,int a,int b){
  124. return r[a]==r[b] && r[a+1]==r[b+1] && r[a+2]==r[b+2];
  125. }
  126. int c12 (int k,int *r,int a,int b){
  127. if (k==2) return r[a]<r[b] || r[a]==r[b] && c12(1,r,a+1,b+1);
  128. else return r[a]<r[b] || r[a]==r[b] && wv[a+1]<wv[b+1];
  129. }
  130. void sort (int *r,int *a,int *b,int n,int m){
  131. int i;
  132. for(i=0;i<n;i++) wv[i]=r[a[i]];
  133. for(i=0;i<m;i++) ws[i]=0;
  134. for(i=0;i<n;i++) ws[wv[i]]++;
  135. for(i=1;i<m;i++) ws[i]+=ws[i-1];
  136. for(i=n-1;i>=0;i--) b[--ws[wv[i]]]=a[i];
  137. }
  138. void DC3 (int *r,int *sa,int n,int m){
  139. int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
  140. r[n]=r[n+1]=0;
  141. for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
  142. sort(r+2,wa,wb,tbc,m);
  143. sort(r+1,wb,wa,tbc,m);
  144. sort(r,wa,wb,tbc,m);
  145. for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
  146. rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
  147. if(p<tbc) DC3(rn,san,tbc,p);
  148. else for(i=0;i<tbc;i++) san[rn[i]]=i;
  149. for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
  150. if(n%3==1) wb[ta++]=n-1;
  151. sort(r,wb,wa,ta,m);
  152. for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
  153. for(i=0,j=0,p=0;i<ta && j<tbc;p++)
  154. sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
  155. for(;i<ta;p++) sa[p]=wa[i++];
  156. for(;j<tbc;p++) sa[p]=wb[j++];
  157. }
  158. int rank[N],height[N],sa[3*N],data[3*N];
  159. void calheight(int *r,int *sa,int n){
  160. // memset(height,0,sizeof(height));
  161. // memset(rank,0,sizeof(rank));
  162. int i,j,k=0;
  163. for(i=1;i<=n;i++) rank[sa[i]]=i;
  164. for(i=0;i<n; height[rank[i++]] = k )
  165. for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
  166. }
  167. int temp[N],n,k;
  168. bool Judge (int mid)
  169. {
  170. int cnt=1;
  171. for (int i=2;i<=n;i++)
  172. if (height[i]<mid)
  173. cnt=1;
  174. else
  175. {
  176. cnt++;
  177. if (cnt >= k) //同一组中个数大于等于k
  178. return true;
  179. }
  180. return false;
  181. }
  182. void Deal (int *data,int n,int m)
  183. {
  184. DC3(data,sa,n+1,m);
  185. calheight(data,sa,n);
  186. int low=0,high=n,mid,ans=0;
  187. while (low<high) //注意二分的写法
  188. {
  189. mid = (low+high)>>1;
  190. if ( Judge(mid) )
  191. ans=mid,low=mid+1;
  192. else high = mid;
  193. }
  194. printf("%d\n",ans);
  195. }
  196. int main ()
  197. {
  198. while (~scanf("%d%d",&n,&k))
  199. {
  200. int i;
  201. for (i=0;i<n;i++)
  202. {
  203. scanf("%d",&data[i]);
  204. temp[i]=data[i];
  205. }
  206. if (n==1 && k==1)
  207. {
  208. printf("1\n");
  209. continue;
  210. }
  211. sort(temp,temp+n);
  212. int sz = unique(temp,temp+n)-temp; //去重
  213. map<int,int> mp;
  214. for (i=0;i<sz;i++) //离散化
  215. mp[ temp[i] ] = i+1;
  216. for (i=0;i<n;i++)
  217. data[i] = mp[ data[i] ];
  218. data[n] = 0;
  219. Deal(data,n,sz+1);
  220. }
  221. return 0;
  222. }

发表评论

表情:
评论列表 (有 0 条评论,285人围观)

还没有评论,来说两句吧...

相关阅读

    相关 重复

    思路:使用后缀数组解决 分析: 1、由于要求最长公共子序列,则需要找到字符串的所有子串,即通过产生字符串的后缀数组实现。 2、由于要求最长的重复子串,则需要对所有子串进行