Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <set>
- #include <unordered_map>
- #include <algorithm>
- #include <string>
- #include <unordered_set>
- #include <list>
- #include <map>
- #include <queue>
- #define mp make_pair
- #define i64 long long;
- #define ui64 unsigned long long;
- using namespace std;
- string s;
- int n;
- vector<int> c;
- vector<int> v;
- vector<int> colors;
- bool cmp(int a, int b) {
- return s[a] < s[b];
- }
- int length = 1;
- bool cmp1(int a, int b) {
- if (c[a] != c[b]) {
- return c[a] < c[b];
- }
- return c[(a + length) % n] < c[(b + length) % n];
- }
- struct SegmentTree {
- SegmentTree(int n) {
- v.resize(4 * n + 1, inf);
- }
- void set(int u, int L, int R, int pos, int val) {
- if (L > pos || R < pos) return;
- if (L == R && pos == L) {
- v[u] = val;
- return;
- }
- int m = (L + R) / 2;
- set(u * 2, L, m, pos, val);
- set(u * 2 + 1, m + 1, R, pos, val);
- v[u] = min(v[u * 2], v[u * 2 + 1]);
- }
- int get(int u, int L, int R, int l, int r) {
- if (L > r || R < l) return inf;
- if (L >= l && R <= r) {
- return v[u];
- }
- int m = (L + R) / 2;
- return min(get(u * 2, L, m, l, r), get(u * 2 + 1, m + 1, R, l, r));
- }
- int inf = 1e9 + 10;
- vector<int> v;
- };
- int get_color_suff(int suf) {
- for (int i = 0; i < colors.size(); ++i) {
- if (suf <= colors[i]) {
- return i;
- }
- }
- exit(-1);
- }
- int main() {
- #ifdef _KOCH
- freopen("input.txt", "r", stdin);
- #else
- // freopen("common.in", "r", stdin);
- // freopen("common.out", "w", stdout);
- #endif
- int symb = 33;
- int k;
- cin >> k;
- colors.resize(k);
- for (int i = 0; i < k; ++i) {
- string a;
- cin >> a;
- s += a;
- colors[i] = s.size();
- s += char(symb + i);
- }
- if (k == 1) {
- s.pop_back();
- cout << s << endl;
- return 0;
- }
- v.resize(s.size());
- c.resize(s.size());
- n = s.size();
- for (int i = 0; i < v.size(); ++i) {
- v[i] = i;
- }
- stable_sort(v.begin(), v.end(), cmp);
- int kek = 0;
- c[v[0]] = 0;
- for (int i = 1; i < v.size(); ++i) {
- if (s[v[i]] == s[v[i - 1]]) {
- c[v[i]] = kek;
- }
- else {
- kek++;
- c[v[i]] = kek;
- }
- }
- for (; length <= v.size(); length *= 2) {
- stable_sort(v.begin(), v.end(), cmp1);
- kek = 0;
- vector<int> tmp(n);
- tmp[v[0]] = 0;
- for (int i = 1; i < v.size(); ++i) {
- if (cmp1(v[i], v[i - 1]) == cmp1(v[i - 1], v[i])) {
- tmp[v[i]] = kek;
- }
- else {
- kek++;
- tmp[v[i]] = kek;
- }
- }
- swap(c, tmp);
- }
- std::vector<int> rev(n);
- vector<int> lcp(n);
- for (int i = 0; i < n; ++i) {
- rev[v[i]] = i;
- }
- for (int i = 0, k = 0; i < n; ++i)
- {
- if (k > 0) {
- k--;
- }
- if (rev[i] == n - 1)
- {
- k = 0;
- continue;
- }
- int j = v[rev[i] + 1];
- while (max(i + k, j + k) < n && s[i + k] == s[j + k]) {
- k++;
- }
- lcp[rev[i]] = k;
- }
- lcp.insert(lcp.begin(), 0);
- SegmentTree st(lcp.size());
- for (int i = 0; i < lcp.size(); ++i) {
- st.set(1, 0, lcp.size() - 1, i, lcp[i]);
- }
- map<int, int> segment_colors;
- int l = 0;
- int r = 0;
- int res = 0;
- int x = 0;
- segment_colors[get_color_suff(v[0])]++;
- while (r != lcp.size()) {
- while (segment_colors.size() != k) {
- r++;
- if (r >= v.size()) {
- break;
- }
- segment_colors[get_color_suff(v[r])]++;
- }
- while (segment_colors.size() >= k) {
- int ans = st.get(1, 0, lcp.size() - 1, l + 1, r);
- if (res < ans) {
- x = v[l+1];
- res = ans;
- }
- auto it = segment_colors.find(get_color_suff(v[l]));
- it->second--;
- if (it->second == 0) {
- segment_colors.erase(it);
- }
- l++;
- }
- }
- for (int i = 0; i < res; ++i) {
- cout << s[x + i];
- }
- cout << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement