标签:
题目链接: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\0" -> "$#a#b#a#c#d#\0" 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 vector<pair<int, int> > tmpArr; 50 for(int i=0; i<len-1; i++) { 51 if(arr[i]!=-1 || p[i]<=1) continue; 52 tmpArr.push_back(make_pair(p[i], i)); 53 } 54 sort(tmpArr.begin(), tmpArr.end(), greater<pair<int, int> >()); 55 set<int> S; 56 int res=0; 57 for(auto & x : tmpArr) { 58 int lim1=x.second-(x.first-1); 59 auto it1=S.lower_bound(lim1); 60 if(it1!=S.end() && lim1<=(*it1) && (*it1)<x.second) { 61 res=max(res, (x.second-(*it1))/2*3); 62 } 63 int lim2=x.second+(x.first-1); 64 auto it2=S.upper_bound(x.second+(x.first-1)); 65 if(it2!=S.begin()) --it2; 66 if(it2!=S.end() && x.second<(*it2) && (*it2)<=lim2) { 67 res=max(res, ((*it2)-x.second)/2*3); 68 } 69 S.insert(x.second); 70 } 71 return res; 72 } 73 void print() { 74 for(int i=0; i<(int)arr.size(); i++) { 75 cout<<i<<"\t\n"[i==(int)arr.size()-1]; 76 } 77 for(int i=0; i<(int)arr.size(); i++) { 78 cout<<arr[i]<<"\t\n"[i==(int)arr.size()-1]; 79 } 80 for(int i=0; i<(int)arr.size(); i++) { 81 cout<<p[i]<<"\t\n"[i==(int)arr.size()-1]; 82 } 83 } 84 } 85 int main() { 86 #ifndef ONLINE_JUDGE 87 freopen("in", "r", stdin); 88 // freopen("out", "w", stdout); 89 #endif 90 int T, now=0; 91 scanf("%d", &T); 92 while(T--) { 93 scanf("%d", &N); 94 arr.resize(N); 95 for(int i=0; i<N; i++) { 96 scanf("%d", &arr[i]); 97 } 98 printf("Case #%d: ", ++now); 99 printf("%d\n", Manacher::go(arr)); 100 } 101 return 0; 102 }
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\0" -> "$#a#b#a#c#d#\0" 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]<<" \n"[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<<"\t\n"[i==(int)arr.size()-1]; 101 } 102 for(int i=0; i<(int)arr.size(); i++) { 103 cout<<arr[i]<<"\t\n"[i==(int)arr.size()-1]; 104 } 105 for(int i=0; i<(int)arr.size(); i++) { 106 cout<<p[i]<<"\t\n"[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\n", Manacher::go(arr)); 124 } 125 return 0; 126 }
[2015hdu多校联赛补题]hdu5371 Hotaru's problem
标签:
原文地址:http://www.cnblogs.com/shjwudp/p/4722466.html