QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#549298 | #5084. Longest Substring | BongoCatEnjoyer | TL | 0ms | 3676kb | C++14 | 5.1kb | 2024-09-06 14:06:22 | 2024-09-06 14:06:23 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
struct SuffixArray {
vi sa, lcp;
SuffixArray(string& s, int lim=256) { // or basic_string<int>
int n = sz(s) + 1, k = 0, a, b;
vi x(all(s)+1), y(n), ws(max(n, lim)), rank(n);
sa = lcp = y, iota(all(sa), 0);
for (int j = 0, p = 0; p < n; j = max(1, j * 2), lim = p) {
p = j, iota(all(y), n - j);
rep(i,0,n) if (sa[i] >= j) y[p++] = sa[i] - j;
fill(all(ws), 0);
rep(i,0,n) ws[x[i]]++;
rep(i,1,lim) ws[i] += ws[i - 1];
for (int i = n; i--;) sa[--ws[x[y[i]]]] = y[i];
swap(x, y), p = 1, x[sa[0]] = 0;
rep(i,1,n) a = sa[i - 1], b = sa[i], x[b] =
(y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 : p++;
}
rep(i,1,n) rank[sa[i]] = i;
for (int i = 0, j; i < n - 1; lcp[rank[i++]] = k)
for (k && k--, j = sa[rank[i] - 1];
s[i + k] == s[j + k]; k++);
}
};
map<int,int> arrL;
map<int,int> arrR;
map< int, tuple<int,int,int,set<int>> > activeRange; // {L, R, len, set}
vector<int> ans;
vector<int> maxD;
void doCalc(int currRange){
auto& tmp = activeRange[currRange];
int l = get<0>(tmp);
int r = get<1>(tmp);
int len = get<2>(tmp);
set<int> idxArr = get<3>(tmp);
int d = 0;
auto curr = idxArr.begin();
while (curr != idxArr.end()){
int currIdx = *curr;
d++;
curr = lower_bound(all(idxArr),currIdx+len);
}
// cout << "hasil d kiri = " << d << " " << l << " to " << r << endl;
int nstring = r-l+2;
if (maxD[nstring] < d){
ans[nstring] = len;
maxD[nstring] = d;
} else if (maxD[nstring] == d){
ans[nstring] = max(len,ans[nstring]);
}
}
int main(){
cin.tie(0)->sync_with_stdio(0);
cin.exceptions(cin.failbit);
string s;
cin >> s;
int n = s.length();
SuffixArray sa = SuffixArray(s);
// for (int i = 1;i <= n;i++){
// cout << sa.sa[i] << " ";
// }
// cout<< endl;
// for (int i = 1;i <= n;i++){
// cout << sa.lcp[i] << " ";
// }
// cout<< endl;
vector<pair<int,int>> sweepArr; // {lcp len, idx}
for (int i = 1;i <= n;i++){
if (sa.lcp[i] != 0) sweepArr.push_back({sa.lcp[i],i});
}
sort(all(sweepArr), [](const pair<int,int> &a, const pair<int,int> &b){
if (a.first == b.first){
return a.second < b.second;
}
return a.first > b.first ;
});
ans.resize(n+1,0);
maxD.resize(n+1,0);
for (int i = 0;i < sweepArr.size();i++){
int len = sweepArr[i].first;
int curIdx = sweepArr[i].second;
int suffIdx = sa.sa[curIdx];
// cout << len << " " << curIdx << " " << suffIdx << endl;
int leftRangeIdx = -1, rightRangeIdx = -1;
if (arrR.count(curIdx-1)){
leftRangeIdx = arrR[curIdx-1];
doCalc(leftRangeIdx);
}
if (arrL.count(curIdx+1)){
rightRangeIdx = arrL[curIdx+1];
doCalc(rightRangeIdx);
}
// cout << leftRangeIdx << " " << rightRangeIdx << endl;
if (leftRangeIdx != -1 && rightRangeIdx != -1){
auto lSuff = get<3>(activeRange[leftRangeIdx]);
auto rSuff = get<3>(activeRange[rightRangeIdx]);
lSuff.insert(all(rSuff));
// lSuff.insert(suffIdx);
arrR.erase(get<1>(activeRange[leftRangeIdx]));
arrL.erase(get<1>(activeRange[rightRangeIdx]));
arrL[get<1>(activeRange[rightRangeIdx])] = leftRangeIdx;
get<1>(activeRange[leftRangeIdx]) = get<1>(activeRange[rightRangeIdx]);
get<2>(activeRange[leftRangeIdx]) = len;
activeRange.erase(rightRangeIdx);
} else if (leftRangeIdx != -1){
arrR.erase(get<1>(activeRange[leftRangeIdx]));
arrR[curIdx] = leftRangeIdx;
get<3>(activeRange[leftRangeIdx]).insert(suffIdx);
get<1>(activeRange[leftRangeIdx]) = curIdx;
get<2>(activeRange[leftRangeIdx]) = len;
} else if (rightRangeIdx != -1){
arrL.erase(get<1>(activeRange[rightRangeIdx]));
arrL[curIdx] = rightRangeIdx;
get<3>(activeRange[rightRangeIdx]).insert(sa.sa[curIdx-1]);
get<0>(activeRange[rightRangeIdx]) = curIdx;
get<2>(activeRange[rightRangeIdx]) = len;
} else {
activeRange[curIdx] = make_tuple(curIdx, curIdx, len, set<int>());
get<3>(activeRange[curIdx]).insert(suffIdx);
get<3>(activeRange[curIdx]).insert(sa.sa[curIdx-1]);
arrL[curIdx] = curIdx;
arrR[curIdx] = curIdx;
}
}
for (auto& tmp : activeRange){
// cout << tmp.first << endl;
doCalc(tmp.first);
}
ans[1] = n;
for (int i = 1;i <= n;i++){
if (i != 1) cout << " ";
cout << ans[i];
}
cout << endl;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3676kb
input:
ababa
output:
5 2 1 0 0
result:
ok single line: '5 2 1 0 0'
Test #2:
score: 0
Accepted
time: 0ms
memory: 3644kb
input:
aaaaaaaa
output:
8 7 6 5 4 3 2 1
result:
ok single line: '8 7 6 5 4 3 2 1'
Test #3:
score: 0
Accepted
time: 0ms
memory: 3568kb
input:
a
output:
1
result:
ok single line: '1'
Test #4:
score: 0
Accepted
time: 0ms
memory: 3572kb
input:
abcdefghijklmnopqrstuvwxyz
output:
26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
result:
ok single line: '26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'
Test #5:
score: -100
Time Limit Exceeded
input:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...