D. Prefix-Suffix Palindrome (马拉车)
题目:传送门
题意:给你字符串 s ,问长度最大的字符串 t = a + b 是什么,其中,t 是回文串, a 是字符串 s 的前缀, b 是字符串 s 的后缀。
思路:
我们先把能构成回文的,前缀和后缀取出来,然后对剩下的字符串,求,最长的前缀回文,最长后缀回文,取两者最大即可。
#include <bits/stdc++.h> #define LL long long #define ULL unsigned long long #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF INT_MAX #define inf LLONG_MAX #define PI acos(-1) #define fir first #define sec second using namespace std; const int N = 1e6 + 5; const LL mod = 1e9 + 7; LL ksm(LL a, LL b) { LL ans = 1LL; while(b) { if(b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } struct manacher { char ch[N << 1]; int p[N << 1]; void work(char *s, int len) { int l = 0; ch[l++] = '&'; ch[l++] = '#'; rep(i, 0, len - 1) { ch[l++] = s[i]; ch[l++] = '#'; } ch[l] = '\0'; int mx = 0, id = 0; rep(i, 0, l - 1) { p[i] = i < mx ? min(p[2 * id - i], mx - i) : 1; while(ch[i + p[i]] == ch[i - p[i]]) p[i]++; if(i + p[i] > mx) mx = i + p[i], id = i; } } bool judge(int l, int r) { int mid = (l * 2 + r * 2) >> 1; return p[mid] - 1 >= r - l + 1; } }Man; char a[N], b[N]; void solve() { int n; scanf("%s", a + 1); n = strlen(a + 1); int L = 1, R = n; while(L < R) { if(a[L] == a[R]) L++, R--; else break; } if(L >= R) { printf("%s\n", a + 1); return ; } int cnt = 0; rep(i, L, R) b[cnt++] = a[i]; Man.work(b, cnt); int res = 0; pair < int, int > tmp; rep(i, 0, cnt - 1) { if(Man.judge(1, i + 1)) { if(i + 1 > res) { res = i + 1; tmp = make(0, i); } } if(Man.judge(i + 1, cnt)) { if(cnt - i > res) { res = cnt - i; tmp = make(i, cnt - 1); } } } rep(i, 1, L - 1) printf("%c", a[i]); rep(i, tmp.first, tmp.sec) printf("%c", b[i]); rep(i, R + 1, n) printf("%c", a[i]); puts(""); } int main() { int _; scanf("%d", &_); while(_--) solve(); // solve(); return 0; }
一步一步,永不停息