Submission #34075

#TimeUsernameProblemLanguageResultExecution timeMemory
34075DoanPhuDucPalindromes (APIO14_palindrome)C++98
100 / 100
799 ms77024 KiB
#include <bits/stdc++.h> #define FOR(x, a, b) for (int x = a; x <= b; ++x) #define FOD(x, a, b) for (int x = a; x >= b; --x) #define REP(x, a, b) for (int x = a; x < b; ++x) #define DEBUG(X) { cout << #X << " = " << X << endl; } #define PR(A, n) { cout << #A << " = "; FOR(_, 1, n) cout << A[_] << " "; cout << endl; } #define PR0(A, n) { cout << #A << " = "; REP(_, 0, n) cout << A[_] << " "; cout << endl; } #define BitCount(x) __builtin_popcount(x) using namespace std; typedef long long LL; const int N = 3e5 + 10; int n; char S[N]; struct PalindromeTree { struct Node { int l, r, Len, suffLink; int nxt[26]; } T[N]; int TSize, suff; void Init() { TSize = suff = 2; T[1].Len = -1; T[1].suffLink = 1; T[2].Len = +0; T[2].suffLink = 1; } void AddLetter(int pos) { int cur = suff; int ltr = S[pos] - 'a'; while (true) { int l = T[cur].Len; if (pos - l - 1 >= 1 && S[pos - l - 1] == S[pos]) break; cur = T[cur].suffLink; } if (T[cur].nxt[ltr]) { suff = T[cur].nxt[ltr]; return; } suff = ++TSize; T[TSize].Len = T[cur].Len + 2; T[TSize].l = pos - T[TSize].Len + 1; T[TSize].r = pos; T[cur].nxt[ltr] = TSize; if (T[TSize].Len == 1) { T[TSize].suffLink = 2; return; } while (true) { cur = T[cur].suffLink; int l = T[cur].Len; if (pos - l - 1 >= 1 && S[pos - l - 1] == S[pos]) { T[TSize].suffLink = T[cur].nxt[ltr]; break; } } } } PT; struct SuffixArray { int n; int SA[N], LCP[N], num[N], L[N], R[N], C[N], pos[N]; char S[N]; bool mark[N]; void Init(string T) { n = T.size() + 1; FOR(i, 1, n - 1) S[i] = T[i - 1]; S[n] = 0; BuildSA(); BuildLCP(); } void BuildSA() { memset(C, 0, sizeof C); FOR(i, 1, n) C[S[i]]++; FOR(i, 1, 255) C[i] += C[i - 1]; FOD(i, n, 1) R[C[S[i]]--] = i; FOR(i, 2, n) mark[i] = S[R[i]] != S[R[i - 1]]; mark[1] = true; for (int k = 1; k <= n; k <<= 1) { int d = 0; FOR(i, 1, n) { if (mark[i]) ++d; num[R[i]] = d; L[i] = (R[i] - k - 1 + 3 * n) % n + 1; } FOR(i, 0, n) C[i] = 0; FOR(i, 1, n) C[num[L[i]]]++; FOR(i, 1, n) C[i] += C[i - 1]; FOD(i, n, 1) R[C[num[L[i]]]--] = L[i]; int p = -1; FOR(i, 1, n) { int x = num[(R[i] + k - 1 + 3 * n) % n + 1]; mark[i] = p != x || num[R[i]] != num[R[i - 1]]; p = x; } } n = n - 1; FOR(i, 0, n) SA[i] = R[i + 1]; } void BuildLCP() { FOR(i, 1, n) pos[SA[i]] = i; int x = 0; LCP[0] = 0; FOR(i, 1, n) { int j = SA[pos[i] - 1]; while (S[i + x] == S[j + x]) ++x; LCP[pos[i]] = x; x = max(x - 1, 0); } } } SA; struct RMQ { static const int LG = 20; int lg[N]; int spT[N][LG + 5]; void Init() { FOR(i, 1, n) spT[i][0] = SA.LCP[i]; for (int j = 1; 1 << j <= n; ++j) for (int i = 1; i + (1 << j) - 1 <= n; ++i) spT[i][j] = min(spT[i][j - 1], spT[i + (1 << (j - 1))][j - 1]); for (int i = 0; 1 << i <= n; ++i) lg[1 << i] = i; FOR(i, 1, n) if (!lg[i]) lg[i] = lg[i - 1]; } int LCP(int l, int r) { int k = lg[r - l + 1]; return min(spT[l][k], spT[r - (1 << k) + 1][k]); } } RMQ; int FindLeft(int i, int Len) { int l = 1, r = i - 1, f = i; while (l <= r) { int m = (l + r) >> 1; if (RMQ.LCP(m + 1, i) >= Len) { f = m; r = m - 1; } else l = m + 1; } return f; } int FindRight(int i, int Len) { int l = i + 1, r = n, f = i; while (l <= r) { int m = (l + r) >> 1; if (RMQ.LCP(i + 1, m) >= Len) { f = m; l = m + 1; } else r = m - 1; } return f; } int main() { #ifdef LOCAL freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif // LOCAL scanf("%s", S + 1); n = strlen(S + 1); PT.Init(); FOR(i, 1, n) PT.AddLetter(i); SA.Init(string(S + 1, S + n + 1)); RMQ.Init(); // PR(SA.SA, n); // PR(SA.LCP, n); LL ans = 0; FOR(i, 3, PT.TSize) { int k = PT.T[i].l, Length = PT.T[i].r - PT.T[i].l + 1; int l = FindLeft(SA.pos[k], Length), r = FindRight(SA.pos[k], Length); ans = max(ans, (LL)(r - l + 1) * Length); } printf("%lld", ans); return 0; }

Compilation message (stderr)

palindrome.cpp: In member function 'void SuffixArray::BuildSA()':
palindrome.cpp:78:28: warning: array subscript has type 'char' [-Wchar-subscripts]
         FOR(i, 1, n) C[S[i]]++;
                            ^
palindrome.cpp:80:30: warning: array subscript has type 'char' [-Wchar-subscripts]
         FOD(i, n, 1) R[C[S[i]]--] = i;
                              ^
palindrome.cpp: In function 'int main()':
palindrome.cpp:162:23: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%s", S + 1); n = strlen(S + 1);
                       ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...