poj 1743 二分答案+后缀数组 求不重叠的最长重复子串

题意:给出一串序列,求最长的theme长度

(theme:完全重叠的子序列,如1 2 3和1 2 3  or  子序列中每个元素对应的差相等,如1 2 3和7 8 9)

要是没有差相等这个条件那就好办多了,直接裸题。

一开始想了个2B方法,后来发现真心2B啊蛤蛤蛤

 1 for i=1 to 88 do
 2 {
 3     for j=1 to length
 4     {
 5         r2[j]=r[j]+i;
 6         if (r2[j]>88)    r2[i]-=88;
 7     }
 8     把新序列r2连接到原序列r的后面
 9     process[r+r2]
10     .....
11     求for i=1->88中得到的最大答案
12 }

正解:http://bbezxcy.iteye.com/blog/1407395

对原序列相邻两元素作差就行了= =

比如:序列8 8 8 15 24 3 3 3

作差得到0 0 7 9 -21 0 0

对新序列再求最长不重叠重复子串,得到的结果+1,就是原序列的最长不重叠重复子串

求最长不重叠重复子串:参考IOI2009论文

Code:

  1 #include "stdio.h"
  2 #include "string.h"
  3 #define maxn 20010
  4
  5 int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
  6 int rank[maxn],height[maxn];
  7 int r[maxn],sa[maxn],ans[maxn];
  8 int n;
  9
 10
 11 int cmp(int *r,int a,int b,int l)
 12 {
 13     return r[a]==r[b]&&r[a+l]==r[b+l];
 14 }
 15
 16 void da(int *r,int *sa,int n,int m)
 17 {
 18     int i,j,p,*x=wa,*y=wb,*t;
 19     for(i=0; i<m; i++) ws[i]=0;
 20     for(i=0; i<n; i++) ws[x[i]=r[i]]++;
 21     for(i=1; i<m; i++) ws[i]+=ws[i-1];
 22     for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
 23     for(j=1,p=1; p<n; j*=2,m=p)
 24     {
 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     }
 36     return;
 37 }
 38
 39 void calheight(int *r,int *sa,int n)
 40 {
 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     return;
 46 }
 47
 48 bool calc(int x)
 49 {
 50     int nm=0;
 51     for (int i=1;i<=n;i++)
 52         if (height[i]<x)
 53         {
 54             nm++;
 55             ans[nm]=i;
 56         }
 57     nm++;
 58     ans[nm]=n+1;
 59     for (int i=0;i<nm;i++)
 60     {
 61         int tl=ans[i],tr=ans[i+1]-1;
 62         int tn=maxn,tx=0;
 63         for (int j=tl;j<=tr;j++)
 64         {
 65             if (tn>sa[j])   tn=sa[j];
 66             if (tx<sa[j])   tx=sa[j];
 67         }
 68         if (tx-tn>=x)   return true;
 69     }
 70     return false;
 71 }
 72
 73 //da(r,sa,n+1,128);
 74 //calheight(r,sa,n);
 75 int main()
 76 {
 77 //    freopen("in.txt","r",stdin);
 78     while (~scanf("%d",&n))
 79     {
 80         if (n!=0)
 81         {
 82             memset(sa,0,sizeof(sa));
 83             memset(height,0,sizeof(height));
 84             memset(ans,0,sizeof(ans));
 85
 86             for (int i=0; i<n; i++)
 87                 scanf("%d",&r[i]);
 88             r[n]=0;
 89
 90 //          for (int i=0;i<=n;i++)
 91 //              printf("%d ",r[i]);
 92 //          printf("\n %d\n",n);
 93
 94             for (int i=1;i<n;i++)
 95                 r[i-1]=r[i]-r[i-1];
 96             n--;
 97             r[n]=0;
 98
 99             for (int i=0;i<n;i++)
100                 r[i]+=100;
101
102 //          for (int i=0;i<=n;i++)
103 //              printf("%d ",r[i]);
104 //          printf("\n %d\n",n);
105
106             da(r,sa,n+1,200);
107             calheight(r,sa,n);
108
109 //          for (int i=0; i<=n; i++)
110 //              printf("%d  %d\n",sa[i],height[i]);
111 //          printf("\n");
112
113             int l=maxn,r=0,res=0;
114             for (int i=1;i<=n;i++)
115             {
116                 if (height[i]<l)   l=height[i];
117                 if (height[i]>r)   r=height[i];
118             }
119             while (r>=l)
120             {
121                 int mid=(l+r)/2;
122                 if (calc(mid))
123                 {
124                     l=mid+1;
125                     res=mid;
126                 }
127                 else
128                     r=mid-1;
129             }
130             res++;
131             if (res<5)  res=0;
132             printf("%d\n",res);
133         }
134     }
135     return 0;
136 }

本题出自USACO5.1 theme,据说是男人八题之一.....orz

时间: 2024-10-24 10:40:14

poj 1743 二分答案+后缀数组 求不重叠的最长重复子串的相关文章

POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)

Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of music

poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列

1 #include "stdio.h" 2 #define maxn 20010 3 4 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; 5 int rank[maxn],height[maxn]; 6 int r[maxn],sa[maxn],ans[maxn]; 7 int n,res,k; 8 9 int cmp(int *r,int a,int b,int l) 10 { 11 return r[a]==r[b]&&r[a+l

POJ - 3261 Milk Patterns (后缀数组求可重叠的 k 次最长重复子串)

Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular pattern

POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. Given two strings A, B and one integer K, we define S, a set of triples (i, j, k): S = {( i, j, k) | k≥ K, A( i, k)= B( j, k)}. You are to give the val

POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

Milk Patterns Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some r

UVA 题目760 DNA Sequencing (后缀数组求两个串最长公共子串,字典序输出)

 DNA Sequencing  A DNA molecule consists of two strands that wrap around each other to resemble a twisted ladder whose sides, made of sugar and phosphate molecules, are connected by rungs of nitrogen-containing chemicals called bases. Each strand is

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树)

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树) 题面 给出一个长度为\(n\)的字符串\(s\),以及\(m\)组询问.每个询问是一个四元组\((a,b,c,d)\),问\(s[a,b]\)的所有子串和字符串\(s[c,d]\)的最长公共前缀长度的最大值. \(n,m \leq 10^5\) 分析 显然答案有单调性.首先我们二分答案\(mid\),考虑如何判定. 如果mid这个答案可行,那么一定存在一个后缀x,它的开头在\([a,

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )

二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; const int maxn = 20009; struct HASH { int id[maxn], N; HASH() { N = 0; } inline void work() { sort(id, id + N); N

自己写的一个后缀树算法查找一个字符串的最长重复子串

在上个星期面试一家公司的笔试题上面的最后一道题就是写程序查找一个字符串的最长重复子串.当时想了很长时间没想出什么好方法,就把一个算法复杂度比较高的算法写上去了.回来上机把那个算法写了一遍测试没问题,然后自己又到网上面查查还有什么方法,然后发现好像有种叫做后缀树的方法,然后看那个方法,当时没给出代码,看图看了老半天加之自己想了好几个小时终于知道后缀树是个什么东西.然后自己萌生了一个自己写一个后缀树算法解决那个重复子串的问题.然后写了一天终于写出来了.后续有做了一些测试,发现自己写的一个只有几十个字