QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#268343#5084. Longest SubstringSTnofarjo#TL 1ms3512kbC++204.1kb2023-11-28 16:01:012023-11-28 16:01:01

Judging History

你现在查看的是最新测评结果

  • [2023-11-28 16:01:01]
  • 评测
  • 测评结果:TL
  • 用时:1ms
  • 内存:3512kb
  • [2023-11-28 16:01:01]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define rep(i,a,b) for (int i=(a); i<(b); ++i)
typedef vector<int> vi;

struct SuffixArray {
	vi sa, lcp;
	SuffixArray(string &s, int lim = 256) {
		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++);
	}
};

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	string s;
	cin >> s;
	int n = s.size();

	SuffixArray sa(s);

	// for (int i=1; i<=n; i++) cout << sa.sa[i] << ' ';
	// cout << '\n';
	// for (int i=1; i<=n; i++) cout << sa.lcp[i] << ' ';
	// cout << '\n';

	vector<int> par(n+1), sez(n+1), lb(n+1), rb(n+1), lst(n+1);
	vector<pair<int, int>> ans(n+1, make_pair(0, 0));
	vector<set<int>> vals(n+1);
	vector<map<int, int>> diffs(n+1);
	auto create = [&](int u, int h) -> void {
		par[u] = lb[u] = rb[u] = u; sez[u] = 1; vals[u].insert(sa.sa[u]);
		lst[u] = h;
	};
	auto find = [&](auto self, int u) -> int {
		if (u != par[u]) return par[u] = self(self, par[u]);
		return u;
	};
	auto unite_set = [&](int u, int v) -> void {
		auto &val = vals[v];
		// auto &diff = diffs[v];
		for (int x : vals[u]) {
			// auto it = val.lower_bound(x);
			// if (it != val.begin()) {
			// 	auto prv = it;
			// 	prv--;
			// 	int y = *it - *prv;
			// 	diff[y]--;
			// 	if (diff[y] == 0) diff.erase(y);
			// }

			val.insert(x);
			// it = val.lower_bound(x);
			// if (it != val.end()) {
			// 	auto nxt = it;
			// 	nxt++;
			// 	if (nxt != val.end()) {
			// 		int y = *nxt - x;
			// 		diff[y]++;
			// 	}
			// 	if (it != val.begin()) {
			// 		auto prv = it;
			// 		prv--;
			// 		int y = x - *prv;
			// 		diff[y]++;
			// 	}
			// }
		}

		vals[u].clear();
		// diffs[u].clear();
	};
	auto calc = [&](int u, int h) -> int {
		int ret = 0, lst = -1;
		for (int l : vals[u]) {
			if (l > lst) {
				ret++;
				lst = l + h - 1;
			}
		}
		return ret;
	};
	auto update_ans = [&](int u, int h) -> void {
		if (h+1 > lst[u]) return;
		int len = rb[u] - lb[u] + 1;
		// cout << lb[u] << ' ' << rb[u] << ' ' << len << ' ' << h+1 << ' ';
		// cout << (diffs[u].empty() ? 1000 : diffs[u].begin()->first) << '\n';
		// int d = (diffs[u].empty() ? 1000000003 : diffs[u].begin()->first);
		// if (ans[len] == 0 && d >= h+1) {
		// 	cout << lb[u] << ' ' << rb[u] << ' ' << len << ' ' << min(d, lst[u]) << '\n';
		// 	ans[len] = min(d, lst[u]); 
		// }
		int lo = h+2, hi = lst[u];
		pair<int, int> best(calc(u, lo), h+1);
		while (lo <= hi) {
			int mid = (lo + hi) / 2;
			int res = calc(u, mid);
			if (res == best.first) {
				best.second = mid;
				lo = mid + 1;
			} else {
				hi = mid - 1;
			}
		}
		ans[len] = max(ans[len], best);
	};
	auto unite = [&](int u, int v, int h) -> void {
		u = find(find, u); v = find(find, v);
		update_ans(u, h); update_ans(v, h);
		if (sez[u] > sez[v]) swap(u, v);
		par[u] = v; sez[v] += sez[u]; lb[v] = min(lb[u], lb[v]); rb[v] = max(rb[u], rb[v]); lst[v] = h;
		unite_set(u, v);
	};

	vector<int> pos(n);
	for (int i=1; i<=n; i++) pos[sa.sa[i]] = i;

	vector<int> idx(n+1);
	for (int i=0; i<=n; i++) idx[i] = i;
	sort(idx.begin()+1, idx.end(), [&](int i, int j) {
		return sa.lcp[i] > sa.lcp[j];
	});
	for (int h=n, i=1; h>0; h--) {
		create(pos[n - h], h);
		while (i <= n && sa.lcp[idx[i]] >= h) {
			int j = idx[i];
			unite(j, j-1, h);
			i++;
		}
	}
	for (int i=1; i<=n; i++) {
		if (i == par[i]) update_ans(i, 0);
	}

	// ans[1] = n;
	for (int i=1; i<=n; i++) cout << ans[i].second << ' ';
	cout << '\n';

	return 0;
}

详细

Test #1:

score: 100
Accepted
time: 1ms
memory: 3496kb

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: 3400kb

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: 1ms
memory: 3512kb

input:

a

output:

1 

result:

ok single line: '1 '

Test #4:

score: 0
Accepted
time: 0ms
memory: 3472kb

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...

output:


result: