题目
题意:
你有一个序列 s s s,还有一个序列 t t t, t t t的组成是有 s s s的前缀和后缀组成的,但是要保证 t t t最后是个回文串,前缀或者后缀可以为空字符串。
思路:
我们可以先求出前缀和后缀相等的字符串有多少,然后将中间的从我们设有k个是相等的,那么我们就要求出中间的从 k k k开始的最长回文是多少,这题可以用暴力解决(有些人的代码是这样的),我这里用的回文自动机做的(但是在第二道题目被卡了QAQ)。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef vector<int> vec;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
const int maxn = 5010;
int len[maxn], fail[maxn], ch[maxn][26], q[maxn];
char str[maxn], s[maxn];
int t, x;
int getfail(int n, int x) {
while (s[n - len[x] - 1] != s[n]) x = fail[x];
return x;
}
string solve() {
int cnt = 1, le = strlen(s + 1), cur = 0;
memset(q, 0, sizeof(q));
memset(len, 0, sizeof(len));
memset(fail, 0, sizeof(fail));
memset(ch, 0, sizeof(ch));
len[1] = -1, fail[0] = 1;
for (int i = 1; i <= le; i++) {
cur = getfail(i, cur);
int now = s[i] - 'a';
q[i] = len[cur] + 2;
if (!ch[cur][now]) {
len[++cnt] = len[cur] + 2;
fail[cnt] = ch[getfail(i, fail[cur])][now];
ch[cur][now] = cnt;
}
cur = ch[cur][now];
}
int Max = 1;
for (int i = 1; i <= le; i++) {
if (i == q[i]) Max = i;
}
string t = "";
for (int i = 1; i <= Max; i++) t += s[i];
return t;
}
int main() {
ios::sync_with_stdio(false);
read(t);
while (t--) {
memset(s, 0, sizeof(s));
int k = 1;
scanf("%s", str + 1);
int len = strlen(str + 1);
for (int i = 1; i <= len; i++) {
if (str[i] == str[len - i + 1]) k++;
else break;
}
if (k > len) {
string t = "";
cout << str + 1 << endl;
continue;
}
int cnt = 1;
for (int i = k; i <= len - k + 1; i++) s[cnt++] = str[i];
string x = solve();
int le = strlen(s + 1);
reverse(s + 1, s + le + 1);
string xx = solve();
for (int i = 1; i < k; i++) cout << str[i];
if (xx.size() > x.size()) cout << xx;
else cout << x;
for (int i = k - 1; i >= 1; i--) cout << str[i];
cout << endl;
}
return 0;
}