#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef unsigned long long ull; #define mp make_pair #define pb push_back #define next _next #define left _left #define right _right const long double eps = 1e-9; const double pi = acos(-1.0); const long long inf = 1e18; using namespace std; // ************************************************* void ensure(bool value, string message){ if(!value){ fprintf(stderr, "Assertion failed. Message = %s", message.c_str()); throw; } } int readInt(int l, int r, string name){ int x; if(scanf("%d", &x) != 1){ fprintf(stderr, "Expected int %s in range [%d, %d], but haven't found!", name.c_str(), l, r); throw; } if(!(l <= x && x <= r)){ fprintf(stderr, "Expected int %s in range [%d, %d], but found %d!", name.c_str(), l, r, x); throw; } return x; } const int __MAXBUF__ = (int)1e7; char __buf__[__MAXBUF__]; string readString(char lfc, char rgc, int lfn, int rgn, string name){ ensure(scanf(" %s ", __buf__) == 1, "Expected string " + name + ", haven't found"); string ans = __buf__; ensure(lfn <= ans.size() && ans.size() <= rgn, "String " + name + " have incorrect length"); for ( int i = 0; i < ans.size(); i++ ) ensure(lfc <= ans[i] && ans[i] <= rgc, "String " + name + " contains incorrect characters"); return ans; } // ************************************************* struct query { int id, l, r, minlen, maxlen; query( int id = 0, int l = 0, int r = 0, int minlen = 0, int maxlen = 0 ) : id( id ), l( l ), r( r ), minlen( minlen ), maxlen( maxlen ) {}; }; bool cmp( query a, query b ) { return a.l > b.l; } string s; int n, m, next[ 100100 ][ 27 ]; int left[ 100100 ][ 27 ], right[ 100100 ][ 27 ]; vector< query > q[ 27 ]; pair< int, int > answer[ 100100 ]; int tree[ 100100 * 4 ], subtree[ 100100 * 4 ]; void init( int v, int l, int r ) { tree[v] = subtree[v] = n + 1; if ( l == r ) return; int x = ( l + r ) / 2; init( v + v, l, x ); init( v + v + 1, x + 1, r ); } void modify( int v, int l, int r, int ll, int rr, int value ) { subtree[ v ] = value; if ( l == ll && rr == r ) { tree[ v ] = value; return; } int x = ( ll + rr ) / 2; if ( l <= x ) modify( v + v, l, min( x, r ), ll, x, value ); if ( x + 1 <= r ) modify( v + v + 1, max( l, x + 1 ), r, x + 1, rr, value ); } int fmin( int v, int l, int r, int ll, int rr ) { if ( l == ll && rr == r ) return subtree[v]; int x = ( ll + rr ) / 2, result = tree[v]; if ( l <= x ) result = min( result, fmin( v + v, l, min( x, r ), ll, x ) ); if ( x + 1 <= r ) result = min( result, fmin( v + v + 1, max( l, x + 1 ), r, x + 1, rr ) ); return result; } void solve() { s = readString( 'a', 'z', 1, 100000, "S" ); n = s.size(); for ( int i = 0; i < 27; i++ ) next[n + 1][i] = n + 1; for ( int i = n; i >= 1; i-- ) for ( int j = 0; j < 27; j++ ) next[i][j] = ( s[i - 1] == 'a' + j ? i : next[i + 1][j] ); for ( int i = 1; i <= n; i++ ) { sort( next[i], next[i] + 27 ); for ( int j = 1; j < 27; j++ ) { left[i][j] = next[i][j - 1]; right[i][j] = next[i][j] - 1; if ( left[i][j] > right[i][j] ) left[i][j] = right[i][j] = -1; } //cerr << "Start " << i << "\n"; //for ( int j = 1; j <= 26; j++ ) cerr << left[i][j] << " " << right[i][j] << "\n"; } m = readInt( 1, 100000, "M" ); for ( int i = 1; i <= m; i++ ) { int x = readInt( 1, 26, "X" ); int minlen = readInt( 1, n, "MinLen" ); int maxlen = readInt( minlen, n, "MaxLen" ); int l = readInt( 0, n - 1, "L" ) + 1; int r = readInt( l - 1, n - 1, "R" ) + 1; q[ x ].push_back( query( i, l, r, minlen, maxlen ) ); } for ( int x = 1; x <= 26; x++ ) { sort( q[x].begin(), q[x].end(), cmp ); int ptr = n + 1; init( 1, 1, n ); for ( int i = 0; i < q[x].size(); i++ ) { //cerr << "Processing " << q[x][i].id << ", L = " << q[x][i].l << " R = " << q[x][i].r << " MinLen = " << q[x][i].minlen << " MaxLen = " << q[x][i].maxlen << "\n"; while ( ptr > q[x][i].l ) { ptr--; if ( left[ ptr ][ x ] != -1 ) { //cerr << "Add " << ptr << " L = " << left[ ptr ][ x ] - ptr + 1 << " R = " << right[ ptr ][ x ] - ptr + 1 << "\n"; modify( 1, left[ ptr ][ x ] - ptr + 1, right[ ptr ][ x ] - ptr + 1, 1, n, ptr ); } } int id = fmin( 1, q[x][i].minlen, q[x][i].maxlen, 1, n ); //cerr << "ID " << id << "\n"; if ( id > n ) continue; int ll = id; int rr = max( left[ id ][ x ], id + q[x][i].minlen - 1 ); if ( q[x][i].l <= ll && rr <= q[x][i].r ) answer[ q[x][i].id ] = make_pair( ll, rr ); } } for ( int i = 1; i <= m; i++ ) printf("%d %d\n", answer[i].first - 1, answer[i].second - 1 ); //for ( int i = 1; i <= m; i++ ) printf("%d\n", answer[i].first ); } int main (int argc, const char * argv[]) { time_t start = clock(); int t = 1; for ( int i = 0; i < t; i++ ) solve(); cerr << fixed << setprecision( 6 ) << "Time: " << 1.0 * ( clock() - start ) / CLOCKS_PER_SEC << "\n"; return 0; }