Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #ifndef ONLINE_JUDGE
- #define W(x, y) cerr << "\033[31m" << #x << " = " << x << "\033[0m" << y;
- #else
- #define W(x, y)
- #endif
- using ll = long long;
- using pii = pair<int, int>;
- using pll = pair<ll, ll>;
- using vi = vector<int>;
- using vii = vector<pii>;
- using vl = vector<ll>;
- using vll = vector<pll>;
- using ld = long double;
- #define ff first
- #define ss second
- const ld pi = acosl(-1);
- const ll prime = 1000000000 + 7;
- const ll INF = 1000000000;
- template<typename F>
- void countsort(vl &ind, F f){
- ll n = ind.size();
- vl cnt(n);
- vl pos(n);
- vl vet_ans(n);
- for(int i = 0; i < n; ++i){
- cnt[f(ind[i])]++;
- }
- for(int i = 1; i < n; ++i){
- pos[i] = pos[i-1] + cnt[i-1];
- }
- for(int i = 0; i < n; ++i){
- ll aux = f(ind[i]);
- vet_ans[pos[aux]] = ind[i];
- pos[aux]++;
- }
- ind = vet_ans;
- }
- struct SparceTable{
- ll n;
- ll m;
- vector<vl> mat;
- vl mylog;
- SparceTable(){
- }
- void init(vl &vet) {
- n = vet.size();
- m = 0;
- while ((1 << m) <= vet.size()){
- m++;
- }
- mat.resize(m, vl(n));
- mylog.resize(n);
- mat[0] = vet;
- for(int i = 1; i < m; ++i){
- for(int j = 0; j < n; ++j){
- if(j+(1 << (i - 1)) < n){
- mat[i][j] = min(mat[i-1][j], mat[i-1][j+(1 << (i - 1))]);
- }
- }
- }
- }
- ll query(ll l, ll r){
- ll res = mat[0][l];
- for(int i = m-1; i >= 0; --i){
- if(l <= r && (r-l+1) >= (1<<i)){
- res = min(res, mat[i][l]);
- l += 1 << i;
- }
- }
- return res;
- }
- };
- struct SufixArray{
- vl ind; // ordem do menor para o maior
- vl val;
- vl prefix_c;
- string s;
- ll n;
- SparceTable st;
- void init(string &t){
- s = t + '$';
- n = s.size();
- ind.resize(n);
- val.resize(n);
- prefix_c.resize(n);
- iota(ind.begin(), ind.end(), 0);
- sort(ind.begin(), ind.end(), [this](ll a, ll b){
- return s[a] < s[b];
- });
- val[ind[0]] = 0;
- for(int i = 1; i < n; ++i){
- val[ind[i]] = val[ind[i-1]];
- if(s[ind[i]] != s[ind[i-1]]){
- val[ind[i]]++;
- }
- }
- for(int z = 0; (1LL << z) <= n; ++z){
- int y = (1LL << z);
- countsort(ind, [&y, this](ll x){
- return val[(x - y + 4 * n)%n];
- });
- vll tmp(n);
- for(int i = 0; i < n; ++i){
- ll aux1 = (ind[i] - y + 4 * n)%n;
- ll aux2 = ind[i];
- tmp[i] = {val[aux1], val[aux2]};
- ind[i] = aux1;
- }
- val[ind[0]] = 0;
- for(int i = 1; i < n; ++i){
- val[ind[i]] = val[ind[i-1]];
- if(tmp[ind[i]] != tmp[ind[i-1]]){
- val[ind[i]]++;
- }
- }
- }
- int k = 0;
- for(int i = 0; i < n; ++i){
- ll p = val[i]; // Qual posição o i está
- if(p == 0){
- continue;
- }
- ll j = ind[p-1]; // vou para posição p-1 e pergunto qual o indice do primeiro caractere
- while(s[i+k] == s[j+k]){
- k++;
- }
- prefix_c[p] = k;
- k = max(k-1, 0);
- }
- st.init(prefix_c);
- }
- ll prefixComum(ll a, ll b){
- return st.query(val[a]+1, val[b]);
- }
- };
- int main(){
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- string s;
- cin >> s;
- ll n = s.size();
- ll m;
- cin >> m;
- vll vet(m);
- for(int i = 0; i < m; ++i){
- cin >> vet[i].ff >> vet[i].ss;
- }
- SufixArray sa;
- sa.init(s);
- sort(vet.begin(), vet.end(), [&sa](pll a, pll b){
- a.ff--;
- a.ss--;
- b.ff--;
- b.ss--;
- ll ta = a.ss-a.ff+1;
- ll tb = b.ss-b.ff+1;
- ll k = sa.prefixComum(a.ff, b.ff);
- if(k >= ta && k >= tb){
- if(ta == tb){
- return a < b;
- } else{
- return ta < tb;
- }
- } else if(k >= ta){
- return ta < tb;
- } else if(k >= tb){
- return ta < tb;
- } else{
- return sa.s[a.ff + k] < sa.s[b.ff + k];
- }
- });
- cerr << endl;
- for(int i = 0; i < m; ++i){
- cout << vet[i].ff << " " << vet[i].ss << "\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement