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;
}
原文地址:https://www.cnblogs.com/baidongtan/p/2671133.html