1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #include "iostream" #include "algorithm" #include "cstring" #include "cstdio" #include "ctime" using namespace std; #define MAXN 200006 int n , m , ps; char ch[MAXN]; namespace solve {
int T[MAXN*20] , ls[MAXN*20] , rs[MAXN*20] , rt[MAXN] , cn; void add( int& rt , int l , int r , int p ) { if( !rt ) rt = ++ cn; ++ T[rt]; if( l == r ) return; int m = l + r >> 1; if( p <= m ) add( ls[rt] , l , m , p ); else add( rs[rt] , m + 1 , r , p ); } int merge( int u , int v , int l , int r ) { if( !u || !v ) return u ^ v; int cur = ++ cn , m = l + r >> 1; T[cur] = T[u] + T[v]; if( l == r ) return cur; ls[cur] = merge( ls[u] , ls[v] , l , m ); rs[cur] = merge( rs[u] , rs[v] , m + 1 , r ); return cur; } int que( int rt , int l , int r , int L , int R ) { if( !rt ) return 0; if( L <= l && R >= r ) return T[rt]; int m = l + r >> 1 , res = 0; if( L <= m ) res += que( ls[rt] , l , m , L , R ); if( R > m ) res += que( rs[rt] , m + 1 , r , L , R ); return res; }
int son[MAXN][26] , len[MAXN] , par[MAXN] , lst[MAXN]; int last , cnt;
int head[MAXN] , to[MAXN] , nex[MAXN] , ecn; void ade( int u , int v ) { to[++ ecn] = v , nex[ecn] = head[u] , head[u] = ecn; } void addall( ) { for( int i = 2 ; i <= cnt ; ++ i ) ade( par[i] , i ); }
void init( ) { cnt = last = 1; } void ins( int c ) { int cur = ++ cnt; len[cur] = len[last] + 1; int p = last; while( p && !son[p][c] ) son[p][c] = cur , p = par[p]; if( !p ) par[cur] = 1; else { int q = son[p][c]; if( len[q] == len[p] + 1 ) par[cur] = q; else { int cl = ++ cnt; memcpy( son[cl] , son[q] , sizeof son[q] ); par[cl] = par[q] , len[cl] = len[p] + 1; par[q] = par[cur] = cl; while( p ) { if( son[p][c] == q ) son[p][c] = cl; p = par[p]; } } } last = cur , lst[++ ps] = cur; add( rt[cur] , 1 , n , ps ); } int G[MAXN][19]; int work( int u , int ln ) { for( int k = 18 ; k >= 0 ; -- k ) if( len[G[u][k]] >= ln ) u = G[u][k]; return u; } void dfs( int u , int fa ) { for( int i = head[u] ; i ; i = nex[i] ) { int v = to[i]; if( v == fa ) continue; G[v][0] = u; for( int k = 1 ; k < 19 ; ++ k ) if( G[G[v][k-1]][k-1] ) G[v][k] = G[G[v][k-1]][k-1]; else break; dfs( v , u ); rt[u] = merge( rt[u] , rt[v] , 1 , n ); } } }
int main() { cin >> n >> m; scanf("%s",ch + 1); using namespace solve; init( ); for( int i = 1 ; i <= n ; ++ i ) ins( ch[i] - 'a' ); addall( ); dfs( 1 , 1 ); for( int i = 1 , a , b , c , d ; i <= m ; ++ i ) { scanf("%d%d%d%d",&a,&b,&c,&d); int l = 1 , r = d - c + 1; while( l <= r ) { int mid = l + r >> 1; int t = work( lst[c + mid - 1] , mid ); if( que( rt[t] , 1 , n , a + mid - 1 , b ) ) l = mid + 1; else r = mid - 1; } printf("%d\n",r); } }
|