• HDU 5371 Hotaru's problem Manacher+尺取法


    题意:给你一个序列,求最长的两段回文子串,要求他们共用中间的一半。

    思路:利用Manacher求出p[i]表示的当前位置的最长回文串长度,然后把每一个长度大于等于2的回文串的左区间和右区间分别放到两个数组里面,由于做manacher时添加了特殊的数字,所以处理的时候稍微注意一下。

      然后把左右区间按照左端点排序,接着根据尺取法来找答案中的那一段重合的部分。对于每一段右区间R[i]而言,只有L[j].right<=R[i].right && L[j].left<=R[i].right 就是有效的,对于这样的情况所得到的有效值就是L[j].right-R[i].left+1, 当然,当L[j].left>R[i].right时,就不能够再处理R[i]了,而是去处理R[i+1]。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #define LL long long
     5 #define MAXN 100005
     6 using namespace std;
     7 int n;
     8 LL s[MAXN * 3];
     9 int p[MAXN];
    10 int f[MAXN];
    11 int m;
    12 struct Node{
    13     int left, right;
    14     int mm;
    15     Node(int left = 0, int right = 0):left(left), right(right){
    16         mm = right - left + 1;
    17     };
    18     bool operator < (const Node & b) const{
    19         return left < b.left;
    20     }
    21 };
    22 vector<Node> L, R;
    23 void manacher(){
    24     int res = 0, id = 0;
    25     for(int i = 1; i <= m; i++) {
    26         if(res > i){
    27             p[i] = min(p[2 * id - i], res - i);
    28         }
    29         else{
    30             p[i] = 1;
    31         }
    32         //p[i] = mx > i? min(mp[2*id-i], mx-i): 1;
    33         while(s[i + p[i]] == s[i - p[i]]){
    34             p[i]++;
    35         }
    36         //while(s[i+mp[i]] == s[i-mp[i]]) mp[i]++;
    37         if(i + p[i] > res) {
    38             res = i + p[i];
    39             id = i;
    40         }
    41     }
    42 }
    43 int main()
    44 {
    45 #ifndef ONLINE_JUDGE
    46     freopen("in.txt", "r", stdin);
    47     //freopen("out.txt", "w", stdout);
    48 #endif // OPEN_FILE
    49     int T;
    50     scanf("%d", &T);
    51     int cas = 1;
    52     while(T--){
    53         scanf("%d", &n);
    54        // char ch;
    55         m = 1;
    56         s[m++] = -2;
    57         s[m++] = -1;
    58         //LL x;
    59         for(int i = 0; i < n; i++){
    60             scanf("%I64d", &s[m++]);
    61             s[m++] = -1;
    62         }
    63         s[m++] = -2;
    64         m--;
    65         manacher();
    66         L.clear();
    67         R.clear();
    68         for(int i = 4; i <= m; i += 2){
    69             if(s[i] != -1 || p[i] == 1) continue;
    70             int x = (i / 2) - 1;
    71             int y = x - ((p[i] - 1) / 2) + 1;
    72             L.push_back(Node(y, x));
    73             x++;
    74             y = x + ((p[i] - 1) / 2) - 1;
    75             R.push_back(Node(x, y));
    76             //printf("%d ", p[i] -1);
    77         }
    78         sort(L.begin(), L.end());
    79         sort(R.begin(), R.end());
    80         /*for(int i = 0; i < R.size(); i++){
    81             printf("%d %d
    ", R[i].left, R[i].right);
    82         }*/
    83         int t = 0;
    84         int ans = 0;
    85         for(int i = 0; i < R.size(); i++){
    86             while(t < L.size() && L[t].left <= R[i].left){
    87                 if(R[i].left <= L[t].right && L[t].right <= R[i].right){
    88                     ans = max(ans, L[t].right - R[i].left + 1);
    89                 }
    90                 t++;
    91             }
    92         }
    93         printf("Case #%d: %d
    ", cas++, ans * 3);
    94     }
    95 }
  • 相关阅读:
    美国航天局的十大编码戒律(转)
    大型数据库应用解决方案总结
    IOCP模型
    SSH 连接慢的解决方案详解
    指针(详解)【转】
    有关推挽输出、开漏输出、复用开漏输出、复用推挽输出以及上拉输入、下拉输入、浮空输入、模拟输入区别【转】
    USB入门开发的八个问题&USB枚举『转』
    浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)(转)
    KEIL Code RO-data RW-data ZI-data 【转】
    262K Color
  • 原文地址:https://www.cnblogs.com/macinchang/p/4726417.html
Copyright © 2020-2023  润新知