码迷,mamicode.com
首页 > 其他好文 > 详细

poj1743 Musical Theme

时间:2017-03-30 00:48:10      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:printf   pre   判断   ==   blog   最大   str   turn   name   

神题!!

2333,要求可以给区间加减同一个数,然后我就懵逼了,,%%题解,可以用差分嘛2333

所以原来的区间长度差分之后就要减一了,

然后现在用sa搞出height数组,然后对于>=len(len为二分的答案长度-1)的区间,去里面sa的最大和最小的差,就是这两个子串相距的最远距离了,判断这个是不是满足>len就好

注意,不能==len,因为这是差分数组,==len的话就相当于重合

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define N 100005
 5 #define inf 0x3f3f3f3f
 6 #define LL long long
 7 #define eps 1e-8
 8 using namespace std;
 9 inline int ra()
10 {
11     int x=0,f=1; char ch=getchar();
12     while (ch<0 || ch>9) {if (ch==-) f=-1; ch=getchar();}
13     while (ch>=0 && ch<=9) {x=x*10+ch-0; ch=getchar();}
14     return x*f;
15 }
16 
17 int sa[2][N],rank[2][N],v[N],height[N];
18 int p=0,q=1,n;
19 int a[N];
20 
21 void get_height()
22 {
23     int k=0;
24     for (int i=1; i<=n; i++)
25     {
26         if (rank[p][i]==1) height[1]=0;
27         else
28         {
29             int j=sa[p][rank[p][i]-1];
30             while (a[i+k]==a[j+k]) k++;
31             height[rank[p][i]]=k; k?k--:k;
32         }
33     }
34 }
35 void cal_sa(int sa[N], int rank[N], int Sa[N], int Rank[N], int k)
36 {
37     for (int i=1; i<=n; i++) v[rank[sa[i]]]=i;
38     for (int i=n; i>=1; i--) if (sa[i]>k) Sa[v[rank[sa[i]-k]]--]=sa[i]-k;
39     for (int i=n-k+1; i<=n; i++) Sa[v[rank[i]]--]=i;
40     for (int i=1; i<=n; i++) Rank[Sa[i]]=Rank[Sa[i-1]]+(rank[Sa[i]]!=rank[Sa[i-1]] || rank[Sa[i]+k]!=rank[Sa[i-1]+k]);
41 }
42 void work()
43 {
44     for (int i=1; i<=n; i++) v[a[i]]++;
45     for (int i=1; i<=200; i++) v[i]+=v[i-1];
46     for (int i=1; i<=n; i++) sa[p][v[a[i]]--]=i;
47     for (int i=1; i<=n; i++) rank[p][sa[p][i]]=rank[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
48     for (int k=1; k<n; k<<=1,swap(p,q)) cal_sa(sa[p],rank[p],sa[q],rank[q],k);
49     get_height();
50 }
51 bool check(int len)
52 {
53     int mn=inf,mx=-inf;
54     for (int i=2; i<=n; i++)
55     {
56         if (height[i]>=len)
57         {
58             mx=max(mx,max(sa[p][i-1],sa[p][i]));
59             mn=min(mn,min(sa[p][i-1],sa[p][i]));
60             if (mx-mn>len) return 1;
61         }
62         else mn=inf,mx=-inf;
63     }
64     return 0;
65 }
66 void solve()
67 {
68     int l=0,r=n>>1,ans=0;
69     while (l<=r)
70     {
71         int mid=l+r>>1;
72         if (check(mid)) ans=mid,l=mid+1; else r=mid-1;
73     }
74     printf("%d\n",ans>=4?ans+1:0);
75 }
76 
77 int main(int argc, char const *argv[])
78 {
79     while (n=ra())
80     {
81         int last;
82         memset(v,0,sizeof(v));
83         for (int i=1; i<=n; i++)
84         {
85             int x=ra();
86             if (i!=1) a[i-1]=x-last+100;
87             last=x;
88         }
89         n--; work();
90         solve();
91     }
92     return 0;
93 }

 

poj1743 Musical Theme

标签:printf   pre   判断   ==   blog   最大   str   turn   name   

原文地址:http://www.cnblogs.com/ccd2333/p/6642193.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!