Submission #3369820
Source Code Expand
#include <bits/stdc++.h> #define ll long long #define REP(i, n) for (ll (i) = 0; (i) < (n); (i)++) #define REPI(i, a, b) for (ll (i) = (a); (i) < (b); (i)++) #define int long long using namespace std; using II = pair<int, int>; using VI = vector<int>; using VVI = vector<VI>; using VVVI = vector<VVI>; using VII = vector<II>; class SuffixArray { void set_lcp() { lcp = VI(N - 1); int h = 0; REP (i, N) { if (h > 0) h--; if (rank[i] == N - 1) continue; int j = sorted[rank[i] + 1]; // 比べる対象(辞書順が一つ大きいもの) for (; i + h < N && j + h < N; h++) { if (S[i + h] != S[j + h]) break; } lcp[rank[i]] = h; } } public: int N; string S; VI rank; // rank[i]: iから始まるsuffixの辞書順での順位 VI sorted; // sorted[i]: suffixが辞書順i番目となる開始位置のindex VI lcp; // lcp[i]: S[sorted[i]...]とS[sorted[i + 1]...]が先頭何文字一致しているか SuffixArray(string s) { S = s; N = S.size(); sorted = VI(N); rank = VI(N); REP (i, N) { sorted[i] = i; rank[i] = S[i]; } int k; function<bool(int, int)> compare_sa = [this, &k](int i, int j) { if (rank[i] != rank[j]) { return rank[i] < rank[j]; } int ri = i + k < N ? rank[i + k] : -1; int rj = j + k < N ? rank[j + k] : -1; return ri < rj; }; for (k = 1; k < N; k *= 2) { sort(sorted.begin(), sorted.end(), compare_sa); VI tmp(N, 0); REPI (i, 1, N) { tmp[sorted[i]] = tmp[sorted[i - 1]] + compare_sa(sorted[i - 1], sorted[i]); } rank = tmp; } set_lcp(); } // sizeがTと等しく初めてT以上になるようなSの部分文字列(sortedのイテレータを返す) VI::iterator lower_bound(string T) { int l = -1, r = N; while (r - l > 1) { int mid = (l + r) / 2; if (S.compare(sorted[mid], T.size(), T) < 0) { l = mid; } else { r = mid; } } return sorted.begin() + r; } // sizeがTと等しく初めてTより大きくなるようなSの部分文字列(sortedのイテレータを返す) VI::iterator upper_bound(string T) { int l = -1, r = N; while (r - l > 1) { int mid = (l + r) / 2; if (S.compare(sorted[mid], T.size(), T) <= 0) { l = mid; } else { r = mid; } } return sorted.begin() + r; } // S2が部分文字列として何回出現するか int count(string S2) { return upper_bound(S2) - lower_bound(S2); } }; signed main() { string S; cin >> S; SuffixArray sa(S); int N = S.size(); int ans = N * (N + 1) * (N + 2) / 6; REP (i, N - 1) { ans -= sa.lcp[i] * (sa.lcp[i] + 1) / 2; } cout << ans << endl; }
Submission Info
Submission Time | |
---|---|
Task | E - 部分文字列 |
User | knshnb |
Language | C++14 (GCC 5.4.1) |
Score | 100 |
Code Size | 2872 Byte |
Status | AC |
Exec Time | 206 ms |
Memory | 2816 KB |
Judge Result
Set Name | Sample | Subtask1 | Subtask2 | Subtask3 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Score / Max Score | 0 / 0 | 15 / 15 | 35 / 35 | 50 / 50 | ||||||||
Status |
|
|
|
|
Set Name | Test Cases |
---|---|
Sample | sample_1.txt, sample_2.txt, sample_3.txt |
Subtask1 | sample_1.txt, sample_2.txt, sample_3.txt, sub1_1.txt, sub1_2.txt, sub1_3.txt, sub1_4.txt, sub1_5.txt, sub1_6.txt, sub1_7.txt, sub1_8.txt, sub1_9.txt |
Subtask2 | sample_1.txt, sample_2.txt, sample_3.txt, sub1_1.txt, sub1_2.txt, sub1_3.txt, sub1_4.txt, sub1_5.txt, sub1_6.txt, sub1_7.txt, sub1_8.txt, sub1_9.txt, sub2_1.txt, sub2_2.txt |
Subtask3 | sample_1.txt, sample_2.txt, sample_3.txt, sub1_1.txt, sub1_2.txt, sub1_3.txt, sub1_4.txt, sub1_5.txt, sub1_6.txt, sub1_7.txt, sub1_8.txt, sub1_9.txt, sub2_1.txt, sub2_2.txt, sub3_1.txt, sub3_2.txt, sub3_3.txt |
Case Name | Status | Exec Time | Memory |
---|---|---|---|
sample_1.txt | AC | 1 ms | 256 KB |
sample_2.txt | AC | 1 ms | 256 KB |
sample_3.txt | AC | 1 ms | 256 KB |
sub1_1.txt | AC | 1 ms | 256 KB |
sub1_2.txt | AC | 1 ms | 256 KB |
sub1_3.txt | AC | 1 ms | 256 KB |
sub1_4.txt | AC | 1 ms | 256 KB |
sub1_5.txt | AC | 1 ms | 256 KB |
sub1_6.txt | AC | 1 ms | 256 KB |
sub1_7.txt | AC | 1 ms | 256 KB |
sub1_8.txt | AC | 1 ms | 256 KB |
sub1_9.txt | AC | 1 ms | 256 KB |
sub2_1.txt | AC | 2 ms | 256 KB |
sub2_2.txt | AC | 3 ms | 256 KB |
sub3_1.txt | AC | 7 ms | 384 KB |
sub3_2.txt | AC | 31 ms | 768 KB |
sub3_3.txt | AC | 206 ms | 2816 KB |