zoukankan      html  css  js  c++  java
  • poj 1743 Musical Theme 求不可重叠最长重复子串(二分答案+height分组)

    题目可转化为一个经典问题:给定一个字符串,求最长重复子串,这两个子串不能重叠。

    解题思路:二分答案。这就转化成判定性的问题。对于每一个答案需要判定该答案是否合法。把height数组分成若干组使得每一组的height都不小于答案k,如果有一组的后缀的sa值的最大值和最小值之差大于k(保证了两个子串不能重复),则答案k成立。

    倍增算法
      1 /*
      2  *Author:       Zhaofa Fang
      3  *Created time: 2013-04-18-16.24
      4  *Language:     C++
      5  */
      6 #include <cstdio>
      7 #include <cstdlib>
      8 #include <sstream>
      9 #include <iostream>
     10 #include <cmath>
     11 #include <cstring>
     12 #include <algorithm>
     13 #include <string>
     14 #include <utility>
     15 #include <vector>
     16 #include <queue>
     17 #include <map>
     18 #include <set>
     19 using namespace std;
     20 
     21 typedef long long ll;
     22 #define DEBUG(x) cout<< #x << ':' << x << endl
     23 #define FOR(i,s,t) for(int i = (s);i <= (t);i++)
     24 #define FORD(i,s,t) for(int i = (s);i >= (t);i--)
     25 #define REP(i,n) FOR(i,0,n-1)
     26 #define REPD(i,n) FORD(i,n-1,0)
     27 #define PII pair<int,int>
     28 #define PB push_back
     29 #define MP make_pair
     30 #define ft first
     31 #define sd second
     32 #define lowbit(x) (x&(-x))
     33 #define INF (1<<30)
     34 
     35 const int maxn = 22011;
     36 int cha[maxn],a[maxn];
     37 int sa[maxn],t1[maxn],t2[maxn],c[maxn];
     38 int rank[maxn],height[maxn];
     39 
     40 void getHeight(int n){
     41     int k = 0;
     42     for(int i=1;i<=n;i++)rank[sa[i]] = i;
     43     for(int i=0;i<n;i++){
     44         if(k)k --;
     45         int j = sa[rank[i]-1];
     46         while(cha[i+k] == cha[j+k])k++;
     47         height[rank[i]] = k;
     48     }
     49 }
     50 bool cmp(int *r,int a,int b,int l){
     51     return (r[a]==r[b] && r[a+l]==r[b+l]);
     52 }
     53 void build_sa(int m,int n){
     54     int i,*x = t1, *y = t2,k,p;
     55     for(i=0;i<m;i++)c[i] = 0;
     56     for(i=0;i<n;i++)c[x[i] = cha[i]]++;
     57     for(i=1;i<m;i++)c[i] += c[i-1];
     58     for(i=n-1;i>=0;i--)sa[-- c[x[i]]] = i;
     59     for(k=1,p=0;p<n;m=p,k<<=1){
     60         p=0;
     61         for(i=n-k;i<n;i++)y[p++] = i;
     62         for(i=0;i<n;i++)if(sa[i]>=k)y[p++] = sa[i]-k;
     63 
     64         for(i=0;i<m;i++)c[i] = 0;
     65         for(i=0;i<n;i++)c[x[y[i]]]++;
     66         for(i=1;i<m;i++)c[i] += c[i-1];
     67         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]] = y[i];
     68         swap(x,y);
     69         p = 1; x[sa[0]] = 0;
     70         for(i=1;i<n;i++)
     71             x[sa[i]] = cmp(y,sa[i-1],sa[i],k)?p-1:p++;
     72     }
     73     getHeight(n-1);
     74 }
     75 
     76 bool check(int m,int n){
     77     int x=sa[1],y=sa[1];
     78     for(int i=2;i<=n;i++){
     79         if(height[i]>=m){
     80             x = min(x,sa[i]);
     81             y = max(y,sa[i]);
     82             if(y-x>m)return true;
     83         }else x = y = sa[i];
     84     }
     85     return false;
     86 }
     87 int solve(int n){
     88     int l=4,r=n/2,ans=0;
     89     while(l<=r){
     90         int m = (l + r) >> 1;
     91         if(check(m,n-1))l = m+1,ans = m;
     92         else r = m - 1;
     93     }
     94     if(ans<4)ans = -1;
     95     return ans+1;
     96 }
     97 int main(){
     98     //freopen("in","r",stdin);
     99     //freopen("out","w",stdout);
    100     int n;
    101     while(~scanf("%d",&n),n){
    102         REP(i,n)scanf("%d",&a[i]);
    103         REP(i,n-1)cha[i] = a[i+1] - a[i] + 87;
    104         cha[n-1] = 0;
    105         build_sa(175,n);
    106         printf("%d\n",solve(n));
    107     }
    108     return 0;
    109 }
    by Farmer
  • 相关阅读:
    发邮件
    加密解密帮助类(对称加密)
    枚举静态类
    【06月05日】A股滚动市净率PB历史新低排名
    【06月04日】A股滚动市盈率PE历史新低排名
    【06月03日】预分红股息率最高排名
    北上资金近1周流入排行榜
    最近一月研报推荐次数最多的最热股票
    【2019年05月28日】指数估值排名
    北上资金近1周流入排行榜
  • 原文地址:https://www.cnblogs.com/fzf123/p/3031733.html
Copyright © 2011-2022 走看看