zoukankan      html  css  js  c++  java
  • [2015hdu多校联赛补题]hdu5371 Hotaru's problem

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371

    题意:把一个数字串A翻过来(abc翻过来为cba)的操作为-A,我们称A-AA这样的串为N-sequence,现在给你一个数字串,问你这个串中最长的N-sequence子串长度

    解:可以想到A-A是一个回文串,-AA也是一个回文串,那么首先Manacher跑一遍求出所有回文子串

    可以想到任意两个互相覆盖串中心点的回文子串都可以表示成N-sequence

    然后大概有三种搞法:

    1、时间复杂度O(N*logN),官方题解的方法。

      将回文子串以从长到短的顺序加到一个set中(插入值为回文子串的中心位置),插入每个串前询问,该串覆盖范围内离它最远的子串中心位置,来更新答案(因为是从长到短插入set的,所以如果后来的串覆盖了某中心,那么该中心所代表的串一定覆盖后来的串

      加了一点注释在代码里面~

    2、时间复杂度O(N*logN*logN),比赛的时候写(shui)的。

      用分治+rmq乱搞了~价值不大,具体可以看代码

    3、时间复杂度O(N^2)。。。吓死了,这个确实有这样子的

      有人N^2剪枝过的,有人用了姿势奇怪的线段树,目测理论复杂度O(N^2)

    O(N*logN)版本:

      1 /*
      2  * Problem: hdu5371  Hotaru's problem
      3  * Author:  SHJWUDP
      4  * Created Time:  2015/8/11 星期二 12:25:41
      5  * File Name: 1006.cpp
      6  * State: Accepted
      7  * Memo: Data struct
      8  */
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <vector>
     12 #include <cstring>
     13 #include <algorithm>
     14 #include <set>
     15 
     16 using namespace std;
     17 
     18 int N;
     19 vector<int> arr;
     20 namespace Manacher {
     21     /**
     22       *    "abacd" -> "$#a#b#a#c#d#"
     23       */
     24     vector<int> arr, p;
     25     
     26     int go(vector<int> & A) {
     27         int len=A.size();
     28         arr.resize(A.size()*2+3);
     29         p.resize(A.size()*2+3);
     30         for(int i=len-1; i>=0; i--) {
     31             arr[i*2+2]=A[i];
     32             arr[i*2+1]=-1;
     33         }
     34         arr[len*2+2]=-2;
     35         arr[len*2+1]=-1;
     36         arr[0]=-2;
     37         len=len*2+2;    ///闭区间
     38         int maxp=0, id;
     39         for(int i=1; i<len-1; i++) {
     40             if(i<maxp) p[i]=min(maxp-i, p[id-(i-id)]);
     41             else p[i]=1;
     42             while(arr[i-p[i]]==arr[i+p[i]]) p[i]++;
     43             if(i+p[i]>maxp) {
     44                 maxp=i+p[i];
     45                 id=i;
     46             }
     47         }
     48 
     49         //可以打印一下p数组,观察下~
     50         vector<pair<int, int> > tmpArr;    //pair(回文串长度, 回文串中心位置)
     51         for(int i=0; i<len-1; i++) {
     52             if(arr[i]!=-1 || p[i]<=1) continue;
     53             tmpArr.push_back(make_pair(p[i], i));
     54         }
     55         sort(tmpArr.begin(), tmpArr.end(), greater<pair<int, int> >());    //按回文串长从大到小排序
     56         set<int> S;
     57         int res=0;
     58         for(auto & x : tmpArr) {
     59             //找当前串左侧覆盖的回文串中心
     60             int lim1=x.second-(x.first-1);    //左侧
     61             auto it1=S.lower_bound(lim1);
     62             if(it1!=S.end()    && lim1<=(*it1) && (*it1)<x.second) {
     63                 res=max(res, (x.second-(*it1))/2*3);
     64             }
     65             //找当前串右侧覆盖的回文串中心
     66             int lim2=x.second+(x.first-1);    //右侧
     67             auto it2=S.upper_bound(x.second+(x.first-1));
     68             if(it2!=S.begin()) --it2;
     69             if(it2!=S.end()    && x.second<(*it2) && (*it2)<=lim2) {
     70                 res=max(res, ((*it2)-x.second)/2*3);
     71             }
     72             S.insert(x.second);
     73         }
     74         return res;
     75     }
     76     void print() {
     77         for(int i=0; i<(int)arr.size(); i++) {
     78             cout<<i<<"	
    "[i==(int)arr.size()-1];
     79         }
     80         for(int i=0; i<(int)arr.size(); i++) {
     81             cout<<arr[i]<<"	
    "[i==(int)arr.size()-1];
     82         }
     83         for(int i=0; i<(int)arr.size(); i++) {
     84             cout<<p[i]<<"	
    "[i==(int)arr.size()-1];
     85         }
     86     }
     87 }
     88 int main() {
     89 #ifndef ONLINE_JUDGE
     90     freopen("in", "r", stdin);
     91 //    freopen("out", "w", stdout);
     92 #endif
     93     int T, now=0;
     94     scanf("%d", &T);
     95     while(T--) {
     96         scanf("%d", &N);
     97         arr.resize(N);
     98         for(int i=0; i<N; i++) {
     99             scanf("%d", &arr[i]);
    100         }
    101         printf("Case #%d: ", ++now);
    102         printf("%d
    ", Manacher::go(arr));
    103     }
    104     return 0;
    105 }
    View Code

    O(N*logN*logN)版本:

      1 /*
      2  * Problem:  
      3  * Author:  SHJWUDP
      4  * Created Time:  2015/8/11 星期二 12:25:41
      5  * File Name: 1006.cpp
      6  * State: 
      7  * Memo: 
      8  */
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <vector>
     12 #include <cstring>
     13 #include <algorithm>
     14 
     15 using namespace std;
     16 
     17 const int INF=0x7f7f7f7f;
     18 
     19 const int MaxA=2e6+7;
     20 
     21 struct RMQ {
     22     int d[MaxA][20];
     23     void init(const vector<int> & A, int n) {
     24         for(int i=0; i<n; i++) d[i][0]=A[i];
     25         for(int j=1; (1<<j)<=n; j++) {
     26             for(int i=0; i+(1<<j)-1<n; i++) {
     27                 d[i][j]=max(d[i][j-1], d[i+(1<<(j-1))][j-1]);
     28             }
     29         }
     30     }
     31     int query(int L, int R) {
     32         int k=0;
     33         while((1<<(k+1)) <= R-L+1) k++;
     34         return max(d[L][k], d[R-(1<<k)+1][k]);
     35     }
     36 };
     37 
     38 int N;
     39 vector<int> arr(MaxA);
     40 namespace Manacher {
     41     /**
     42       *    "abacd" -> "$#a#b#a#c#d#"
     43       */
     44     vector<int> arr(MaxA), p(MaxA), tmpArr(MaxA);
     45     RMQ rmq;
     46 
     47     int dc(int lft, int rgt, int x) {
     48         if(lft>=rgt) return lft;
     49         int mid=(lft+rgt)>>1;
     50         int res=-1;
     51         if(rmq.query(lft, mid)>=x) res=dc(lft, mid, x);
     52         else if(mid+1<=rgt && rmq.query(mid+1, rgt)>=x) res=dc(mid+1, rgt, x);
     53         return res;
     54     }
     55 
     56     int go(vector<int> & A) {
     57         int len=N, lim=len*2+3;
     58         for(int i=len-1; i>=0; i--) {
     59             arr[i*2+2]=A[i];
     60             arr[i*2+1]=-1;
     61         }
     62         arr[len*2+2]=-2;
     63         arr[len*2+1]=-1;
     64         arr[0]=-2;
     65         len=len*2+2;    ///闭区间
     66         int maxp=0, id;
     67         for(int i=1; i<len-1; i++) {
     68             if(i<maxp) p[i]=min(maxp-i, p[id-(i-id)]);
     69             else p[i]=1;
     70             while(arr[i-p[i]]==arr[i+p[i]]) p[i]++;
     71             if(i+p[i]>maxp) {
     72                 maxp=i+p[i];
     73                 id=i;
     74             }
     75         }
     76         
     77         for(int i=0; i<lim; i++) {
     78             if(arr[i]!=-1) {
     79                 tmpArr[i]=-INF;
     80             } else {
     81                 tmpArr[i]=i+p[i]-1;
     82             }
     83     //        cout<<tmpArr[i]<<" 
    "[i==(int)p.size()-1];
     84         }
     85 
     86         rmq.init(tmpArr, lim);
     87         int res=0;
     88         for(int i=0; i<len-1; i++) {
     89             if(arr[i]!=-1 || p[i]<=1) continue;
     90     //        cout<<"to "<<i<<endl;
     91             int lft=i-(p[i]-1), rgt=i-1;
     92             int tmp=dc(lft, rgt, i);
     93     //        cout<<"tmp: "<<tmp<<endl;
     94             if(tmp!=-1) res=max(res, (i-tmp+1)/2*3);
     95         }
     96         return res;
     97     }
     98     void print() {
     99         for(int i=0; i<(int)arr.size(); i++) {
    100             cout<<i<<"	
    "[i==(int)arr.size()-1];
    101         }
    102         for(int i=0; i<(int)arr.size(); i++) {
    103             cout<<arr[i]<<"	
    "[i==(int)arr.size()-1];
    104         }
    105         for(int i=0; i<(int)arr.size(); i++) {
    106             cout<<p[i]<<"	
    "[i==(int)arr.size()-1];
    107         }
    108     }
    109 }
    110 int main() {
    111 #ifndef ONLINE_JUDGE
    112     freopen("in", "r", stdin);
    113 //    freopen("out", "w", stdout);
    114 #endif
    115     int T, now=0;
    116     scanf("%d", &T);
    117     while(T--) {
    118         scanf("%d", &N);
    119         for(int i=0; i<N; i++) {
    120             scanf("%d", &arr[i]);
    121         }
    122         printf("Case #%d: ", ++now);
    123         printf("%d
    ", Manacher::go(arr));
    124     }
    125     return 0;
    126 }
    View Code
  • 相关阅读:
    python笔记005-字符串-列表-元组
    Python笔记2 标准数据类型
    VS2010与VAssistX
    【Windows核心编程】Windows常见数据类型
    网络安全加密
    防御 XSS 的七条原则
    用户权限初略设计
    [Android]Handler的消息机制
    java的线程中的Runnable
    [转]永久告别Android的背景选择器Selector!无需切很多图了!
  • 原文地址:https://www.cnblogs.com/shjwudp/p/4722466.html
Copyright © 2011-2022 走看看