input | output |
---|---|
ThesampletextthatcouldbereadedthesameinbothordersArozaupalanalapuazorA |
ArozaupalanalapuazorA |
Manacher模版题,但是学习到如何输出对应的回文串,即开始坐标=(id-p[id]+1)>>1
代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<sstream> #include<cstring> #include<cstdio> #include<string> #include<deque> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> #define INF 0x3f3f3f3f #define MM(x) memset(x,0,sizeof(x)) using namespace std; typedef long long LL; const int N = 1010; char s[N], ss[2 * N]; int p[2 * N]; inline int manacher(char s[]) { int mx = p[0] = 0, idd, len = strlen(s), S = 0, L = 0; for (int i = 1; i < len; i++) { p[i] = 1; if (mx > i) { p[i] = p[2 * idd - i]; if (mx - i < p[i]) p[i] = mx - i; } while (s[i - p[i]] == s[i + p[i]]) p[i]++; if (i + p[i] > mx) { mx = i + p[i]; idd = i; if (p[i] > S) S = p[i]; } } return S; } int main(void) { int i, j; while (~scanf("%s", s)) { ss[0] = ‘$‘; int len = strlen(s); for (i = 0; i < len; i++) { ss[2 * i + 1] = ‘#‘; ss[2 * i + 2] = s[i]; } ss[2 * len + 1] = ‘#‘; int LEN = manacher(ss) - 1; int idd = 0; for (i = 1; i < 2 * len + 1; i++) { if (p[i] > p[idd]) idd = i; } int cnt = 0; for (i = (idd - p[idd] + 1) >> 1; cnt < LEN; i++, cnt++) putchar(s[i]); putchar(‘\n‘); MM(s); MM(ss); MM(p); } return 0; }
玩了下后缀数组,调了半天终于调出来了,注意一些区间合法判断就好了
代码:
#include <stdio.h> #include <iostream> #include <algorithm> #include <cstdlib> #include <cstring> #include <bitset> #include <string> #include <stack> #include <cmath> #include <queue> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) #define fin(name) freopen(name,"r",stdin) #define fout(name) freopen(name,"w",stdout) #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); typedef pair<int, int> pii; typedef long long LL; const double PI = acos(-1.0); const int N = 220010; int wa[N], wb[N], cnt[N], sa[N]; int ran[N], height[N]; char s[N]; inline int cmp(int r[], int a, int b, int d) { return r[a] == r[b] && r[a + d] == r[b + d]; } void DA(int n, int m) { int i; int *x = wa, *y = wb; for (i = 0; i < m; ++i) cnt[i] = 0; for (i = 0; i < n; ++i) ++cnt[x[i] = s[i]]; for (i = 1; i < m; ++i) cnt[i] += cnt[i - 1]; for (i = n - 1; i >= 0; --i) sa[--cnt[x[i]]] = i; for (int k = 1; k <= n; k <<= 1) { int p = 0; for (i = n - k; i < n; ++i) y[p++] = i; for (i = 0; i < n; ++i) if (sa[i] >= k) y[p++] = sa[i] - k; for (i = 0; i < m; ++i) cnt[i] = 0; for (i = 0; i < n; ++i) ++cnt[x[y[i]]]; for (i = 1; i < m; ++i) cnt[i] += cnt[i - 1]; for (i = n - 1; i >= 0; --i) sa[--cnt[x[y[i]]]] = y[i]; swap(x, y); x[sa[0]] = 0; p = 1; for (i = 1; i < n; ++i) x[sa[i]] = cmp(y, sa[i - 1], sa[i], k) ? p - 1 : p++; m = p; if (m >= n) break; } } void gethgt(int n) { int i, k = 0; for (i = 1; i <= n; ++i) ran[sa[i]] = i; for (i = 0; i < n; ++i) { if (k) --k; int j = sa[ran[i] - 1]; while (s[j + k] == s[i + k]) ++k; height[ran[i]] = k; } } namespace SG { int dp[N][18]; void init(int l, int r) { int i, j; for (i = l; i <= r; ++i) dp[i][0] = height[i]; for (j = 1; l + (1 << j) - 1 <= r; ++j) { for (i = l; i + (1 << j) - 1 <= r; ++i) dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } } int ask(int l, int r) { int len = r - l + 1; int k = 0; while (1 << (k + 1) <= len) ++k; return min(dp[l][k], dp[r - (1 << k) + 1][k]); } int LCP(int l, int r, int len) { if (l > r) swap(l, r); if (l == r) return len - sa[l]; return ask(l + 1, r); } } int main(void) { int i; while (~scanf("%s", s)) { int len = strlen(s); for (i = 0; i < len; ++i) s[len + i] = s[len - 1 - i]; s[len << 1] = ‘\0‘; DA(len << 1 | 1, ‘z‘ + 1); gethgt(len << 1); SG::init(1, len << 1); int ans = 1; int pos = 0; for (i = 0; i < len; ++i)//枚举以i为中心的奇数情况 { if (i + 1 < len && len * 2 - 1 - (i - 1) < len * 2) { int lcp = SG::LCP(ran[i + 1], ran[len * 2 - 1 - (i - 1)], len); lcp = min({lcp, i, len - 1 - i}); int Ans = lcp * 2 + 1; if (Ans > ans || (Ans == ans && i - lcp < pos)) { ans = Ans; pos = i - lcp; } } if (len * 2 - 1 - (i - 1) < len * 2)//以i为靠右位置的偶数情况 { int lcp = SG::LCP(ran[i], ran[len * 2 - 1 - (i - 1)], len); lcp = min({lcp, len - i, i}); int Ans = lcp * 2; if (Ans > ans || (Ans == ans && i - lcp < pos)) { ans = Ans; pos = i - lcp; } } } printf("%d\n", ans); } return 0; }
Ural 1297 Palindrome(Manacher或者后缀数组+RMQ-ST)
原文:http://www.cnblogs.com/Blackops/p/5766356.html