题目大意
给出一份文本文档,要求在这份文档中找出最长回文串(回文串忽略符号,即只包含大小写字母),并输出原文(即符号也要输出).
题解
实际上不就是一个manacher算法模板题嘛.
但是首先要忽略了符号,注意,回车换行符也算是一个符号.
manacher算法实际上就是一个DP.网上有很多资料,这里不再细说.
然后在manacher的过程中加入记录字符在原文中的位置即可.
代码
/* TASK:calfflac LANG:C++ */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 20005; char text[MAXN + 1000], mc[MAXN * 2]; int f[MAXN * 2], key[MAXN * 2], totlen, n, maxr, ans; bool check(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } char upcase(char c) { if (c >= 'A' && c <= 'Z') return c; else return c - 'a' + 'A'; } int main() { freopen("calfflac.in", "r", stdin); freopen("calfflac.out", "w", stdout); totlen = 0; while (fgets(mc, 100, stdin)) { n = strlen(mc); for (int i = totlen; i < totlen + n; ++i) text[i] = mc[i - totlen]; totlen += n; } n = 0; memset(mc, 0, sizeof(mc)); for (int i = 0; i < totlen; ++i) if (check(text[i])) mc[n++] = upcase(text[i]), key[n-1] = i, mc[n++] = '#'; memset(f, 0, sizeof(f)); maxr = 0; ans = 0; for (int i = 1; i < n; ++i) { if (maxr + f[maxr] >= i) { int j = 2 * maxr - i; if (j - f[j] >= maxr - f[maxr]) f[i] = f[j]; else { int l = 0; f[i] = j - maxr + f[maxr]; while (mc[i - f[i] - l - 1] == mc[i + f[i] + l + 1]) l++; f[i] += l; if (mc[i + f[i]] == '#' && f[i] > 0) f[i]--; if (maxr + f[maxr] < i + f[i]) maxr = i; if (f[ans] < f[i]) ans = i; } } else { int l = 0; while (mc[i - l - 1] == mc[i + l + 1]) l++; f[i] = l; if (mc[i + f[i]] == '#' && f[i] > 0) f[i]--; if (maxr + f[maxr] < i + f[i]) maxr = i; if (f[ans] < f[i]) ans = i; } } printf("%d ", f[ans] + 1); for (int i = key[ans - f[ans]]; i <= key[ans + f[ans]]; ++i) printf("%c", text[i]); printf(" "); return 0; }