zoukankan      html  css  js  c++  java
  • bit 最牛的回文

     

    最牛的回文

    Description

    说,如果有无穷多的母牛和无穷多的大型键盘,它们就可以创造出世界上最伟大的回文。在寻找回文时,可以不计文中的标点、空白和大小写,只要关注 26 个英文字母就可以了。但是要注意,在输出时要按照原样,也就是要保留原有的空白、标点和大小写。你的任务,就是在不超过 20000 个字符的字符串中,寻找长度不超过 2000 的回文字符串(含空格和标点时)。

    Input

    一段文本,不超过 20000 个字符,可以有一行或多行,每行的长度不超过 80 个字符。

    Output

    输出的第一行为找到的最长的回文字符串的长度。后面的行应该包括该字符串,字符串两边多余的空格和标点都不需要输出,但字符串中的空格、标点和换行则需要按照原样输出。如果文中有多个长度相同的回文字符串,只要输出第一个就可以了。

     

    Sample Input

    Sonic: Makam, I'm Akam.

     

    Sample Output

    11

    Makam, I'm Akam

     

    分析:最长回文串问题,利用manacher算法复杂度为O(n)。关键在找最长时,要注意回文半径和实际回文长度的区别。另外就是通过穿插字符使回文长度奇偶统一化。

     

    #include<stdio.h>
    #include<string.h>
    #define MAXN 40010
    char a[MAXN], b[MAXN], c[MAXN * 2];
    int pos[MAXN], r[MAXN * 2];
    int len1, len2, len3;
    
    int main() {
        int i, j, k, maxr, start, end, s, e;
        char ch;
        while (scanf("%c", &ch) != EOF) {
            //    if (ch == '1')
            //      break;
            a[len1++] = ch;
        }
        for (i = 0; i < len1; ++i) {
            if (a[i] >= 'a' && a[i] <= 'z') {
                b[len2] = a[i];
                pos[len2++] = i;
            } else if (a[i] >= 'A' && a[i] <= 'Z') {
                b[len2] = a[i] + 32;
                pos[len2++] = i;
    
            }
        }
    
        for (i = 0; i < len2; ++i)
    
            c[0] = '~';
        for (i = 0; i < len2; ++i) {
            c[2 * i + 1] = b[i];
            c[2 * i + 2] = '!';
        }
        c[2 * len2] = '@';
        len3 = len2 * 2 + 1;
        j = 0;
    
        for (i = 1; i < len3 - 1; i += k) {
            while (c[i - j - 1] == c[i + j + 1])
                ++j;
            r[i] = j;
            for (k = 1; k < r[i]; ++k) {
                if (r[i] - k == r[i - k])
                    break;
                if (r[i] - k < r[i - k])
                    r[i + k] = r[i] - k;
                else
                    r[i + k] = r[i - k];
            }
            j = r[i] - k > 0 ? (r[i] - k) : 0;
        }
        maxr = -1;
        for (i = 1; i < len3 - 1; ++i) {
            if (c[i + r[i]] >= 'a' && c[i + r[i]] <= 'z') {
                if (r[i] + 1 > maxr) {
                    start = pos[(i - r[i]) / 2];
                    end = pos[(i + r[i]) / 2];
                    if (end - start + 1 > 2000)
                        continue;
                    maxr = r[i] + 1;
                    s = start;
                    e = end;
                }
            }
            else {
                if (r[i] > maxr) {
                    start = pos[(i - r[i]) / 2];
                    end = pos[(i + r[i]) / 2 - 1];
                    if (end - start + 1 > 2000)
                        continue;
                    maxr = r[i];
                    s = start;
                    e = end;
                }
            }
        }
        printf("%d\n", maxr);
        for (i = start; i <= end; ++i)
            printf("%c", a[i]);
        printf("\n");
        return 0;
    }
  • 相关阅读:
    指数
    汉诺塔问题
    只用递归和当前的栈实现栈的逆序
    让你996的不是你的老板,而是其他愿意996的人
    luke towan
    2020-9-3
    2020-9-3
    springboot注解
    2020-9-2
    20200827
  • 原文地址:https://www.cnblogs.com/baidongtan/p/2671133.html
Copyright © 2011-2022 走看看