#include "bits/stdc++.h"
using namespace std;
using ll = long long ;
#define all(x) x.begin(), x.end()
#ifdef debug_local
#include "debug.h"
#else
#define pr(...) 42
#define prs(...) 42
#endif
static char buf[ 400 << 20 ] ;
void * operator new ( size_t s) {
static size_t i = sizeof buf;
assert ( s < i) ;
return ( void * ) & buf[ i - = s] ;
}
void operator delete ( void * ) { }
struct Value {
int sum;
Value( int x) : sum( x) { } ;
Value( ) : sum( 0 ) { } ;
Value operator+ ( const Value & right) const {
Value left = * this ;
Value ret = Value( ) ;
ret.sum = left.sum + right.sum ;
return ret;
}
} ;
const Value vid = Value( ) ;
struct Node {
Value val;
Node * l;
Node * r;
Node( Value x) : val( x) , l( nullptr) , r( nullptr) { }
Node( Node * ll, Node * rr) {
l = ll, r = rr;
val = ( l ? l- > val : vid) + ( r ? r- > val : vid) ;
}
Node( Node * cpy) : val( cpy- > val) , l( cpy- > l) , r( cpy- > r) { }
} ;
Node * build( int l, int r, vector< Value> & a) {
if ( l + 1 == r) {
return new Node( a[ l] ) ;
}
int m = ( l + r) / 2 ;
return new Node( build( l, m, a) , build( m, r, a) ) ;
}
Node * update( Node * node, Value val, int pos, int l, int r) {
if ( l + 1 == r) {
return new Node( val) ;
}
int m = ( l + r) / 2 ;
if ( m > pos) {
return new Node( update( node- > l, val, pos, l, m) , node- > r) ;
} else {
return new Node( node- > l, update( node- > r, val, pos, m, r) ) ;
}
}
Value query( Node * node, int l, int r, int ql, int qr) {
if ( l >= qr || ql >= r) {
return vid;
}
if ( ql <= l && r <= qr) {
return node- > val;
}
int m = ( l + r) / 2 ;
return query( node- > l, l, m, ql, qr) + query( node- > r, m, r, ql, qr) ;
}
template < int sigma = 29 , char mch = 'a' > struct eertree {
eertree( size_t q) {
q + = 2 ;
s = string( q, - 1 ) ;
len = vector< int > ( q, 0 ) ;
to.resize ( q) ;
link.resize ( q, 0 ) ;
pos.resize ( q, - 1 ) ;
link[ 0 ] = 1 ;
link[ 1 ] = 1 ;
len[ 1 ] = - 1 ;
}
pair< int , int > add_letter( char c, int id) {
c - = 'a' ;
s[ n++ ] = c;
while ( c ! = s[ n - len[ last] - 2 ] )
last = link[ last] ;
if ( ! to[ last] [ c] ) {
int cur = sz++ ;
len[ cur] = len[ last] + 2 ;
pos[ cur] = - 1 ;
if ( len[ cur] == 1 ) {
link[ cur] = 0 ;
} else {
int p = link[ last] ;
while ( c ! = s[ n - len[ p] - 2 ] )
p = link[ p] ;
link[ cur] = to[ p] [ c] ;
}
to[ last] [ c] = cur;
}
last = to[ last] [ c] ;
int x = pos[ last] ;
pos[ last] = id + 1 - len[ last] ;
int y = pos[ last] ;
return { x, y} ;
}
private :
vector< array< int , sigma>> to;
vector< int > link;
vector< int > len, pos;
string s;
int n = 1 , sz = 2 , last = 0 ;
} ;
const int N = ( int ) 1e5 + 1 ;
void solve( int tc = 1 ) {
int n;
cin >> n;
int q;
cin >> q;
string u;
array< int , N> l, r;
for ( int i = 0 ; i < n; i++ ) {
string s;
cin >> s;
l[ i] = u.size ( ) ;
u + = s;
u + = 'a' + 27 ;
u + = 'a' + 28 ;
r[ i] = u.size ( ) - 1 ;
}
pr( u, l, r) ;
n = u.size ( ) ;
vector< Node * > seg( n) ;
vector< Value> v( n, 0 ) ;
auto paltree = eertree( n + 5 ) ;
auto now = build( 0 , n, v) ;
for ( int i = 0 ; i < n; ++ i) {
auto [ x, y] = paltree.add_letter ( u[ i] , i) ;
if ( x ! = - 1 ) {
int val = query( now, 0 , n, x, x + 1 ) .sum ;
now = update( now, val - 1 , x, 0 , n) ;
}
int val = query( now, 0 , n, y, y + 1 ) .sum ;
now = update( now, val + 1 , y, 0 , n) ;
seg[ i] = now;
}
for ( int i = 0 ; i < q; i++ ) {
int x, y;
cin >> x >> y;
-- x;
-- y;
int lq = l[ x] ;
int rq = r[ y] ;
cout << query( seg[ rq] , 0 , n, lq, rq + 1 ) .sum - 2 << '\n ' ;
cout .flush ( ) ;
}
return ;
}
signed main( ) {
cin .tie ( 0 ) - > sync_with_stdio( 0 ) ;
cout << setprecision( 16 ) << fixed;
cerr << setprecision( 4 ) << fixed;
int tc = 1 ;
// cin >> tc;
for ( int t = 1 ; t <= tc; t++ ) {
solve( t) ;
}
}
I2luY2x1ZGUgImJpdHMvc3RkYysrLmgiCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwp1c2luZyBsbCA9IGxvbmcgbG9uZzsKI2RlZmluZSBhbGwoeCkgeC5iZWdpbigpLCB4LmVuZCgpCgojaWZkZWYgZGVidWdfbG9jYWwKI2luY2x1ZGUgImRlYnVnLmgiCiNlbHNlCiNkZWZpbmUgcHIoLi4uKSA0MgojZGVmaW5lIHBycyguLi4pIDQyCiNlbmRpZgoKc3RhdGljIGNoYXIgYnVmWzQwMCA8PCAyMF07CnZvaWQgKm9wZXJhdG9yIG5ldyhzaXplX3QgcykgewogIHN0YXRpYyBzaXplX3QgaSA9IHNpemVvZiBidWY7CiAgYXNzZXJ0KHMgPCBpKTsKICByZXR1cm4gKHZvaWQgKikmYnVmW2kgLT0gc107Cn0Kdm9pZCBvcGVyYXRvciBkZWxldGUodm9pZCAqKSB7fQoKc3RydWN0IFZhbHVlIHsKICBpbnQgc3VtOwogIFZhbHVlKGludCB4KSA6IHN1bSh4KSB7fTsKICBWYWx1ZSgpIDogc3VtKDApIHt9OwoKICBWYWx1ZSBvcGVyYXRvcisoY29uc3QgVmFsdWUgJnJpZ2h0KSBjb25zdCB7CiAgICBWYWx1ZSBsZWZ0ID0gKnRoaXM7CiAgICBWYWx1ZSByZXQgPSBWYWx1ZSgpOwogICAgcmV0LnN1bSA9IGxlZnQuc3VtICsgcmlnaHQuc3VtOwogICAgcmV0dXJuIHJldDsKICB9Cn07Cgpjb25zdCBWYWx1ZSB2aWQgPSBWYWx1ZSgpOwoKc3RydWN0IE5vZGUgewogIFZhbHVlIHZhbDsKICBOb2RlICpsOwogIE5vZGUgKnI7CiAgTm9kZShWYWx1ZSB4KSA6IHZhbCh4KSwgbChudWxscHRyKSwgcihudWxscHRyKSB7fQogIE5vZGUoTm9kZSAqbGwsIE5vZGUgKnJyKSB7CiAgICBsID0gbGwsIHIgPSBycjsKICAgIHZhbCA9IChsID8gbC0+dmFsIDogdmlkKSArIChyID8gci0+dmFsIDogdmlkKTsKICB9CiAgTm9kZShOb2RlICpjcHkpIDogdmFsKGNweS0+dmFsKSwgbChjcHktPmwpLCByKGNweS0+cikge30KfTsKCk5vZGUgKmJ1aWxkKGludCBsLCBpbnQgciwgdmVjdG9yPFZhbHVlPiAmYSkgewogIGlmIChsICsgMSA9PSByKSB7CiAgICByZXR1cm4gbmV3IE5vZGUoYVtsXSk7CiAgfQogIGludCBtID0gKGwgKyByKSAvIDI7CiAgcmV0dXJuIG5ldyBOb2RlKGJ1aWxkKGwsIG0sIGEpLCBidWlsZChtLCByLCBhKSk7Cn0KCk5vZGUgKnVwZGF0ZShOb2RlICpub2RlLCBWYWx1ZSB2YWwsIGludCBwb3MsIGludCBsLCBpbnQgcikgewogIGlmIChsICsgMSA9PSByKSB7CiAgICByZXR1cm4gbmV3IE5vZGUodmFsKTsKICB9CiAgaW50IG0gPSAobCArIHIpIC8gMjsKICBpZiAobSA+IHBvcykgewogICAgcmV0dXJuIG5ldyBOb2RlKHVwZGF0ZShub2RlLT5sLCB2YWwsIHBvcywgbCwgbSksIG5vZGUtPnIpOwogIH0gZWxzZSB7CiAgICByZXR1cm4gbmV3IE5vZGUobm9kZS0+bCwgdXBkYXRlKG5vZGUtPnIsIHZhbCwgcG9zLCBtLCByKSk7CiAgfQp9ClZhbHVlIHF1ZXJ5KE5vZGUgKm5vZGUsIGludCBsLCBpbnQgciwgaW50IHFsLCBpbnQgcXIpIHsKICBpZiAobCA+PSBxciB8fCBxbCA+PSByKSB7CiAgICByZXR1cm4gdmlkOwogIH0KICBpZiAocWwgPD0gbCAmJiByIDw9IHFyKSB7CiAgICByZXR1cm4gbm9kZS0+dmFsOwogIH0KICBpbnQgbSA9IChsICsgcikgLyAyOwogIHJldHVybiBxdWVyeShub2RlLT5sLCBsLCBtLCBxbCwgcXIpICsgcXVlcnkobm9kZS0+ciwgbSwgciwgcWwsIHFyKTsKfQoKdGVtcGxhdGUgPGludCBzaWdtYSA9IDI5LCBjaGFyIG1jaCA9ICdhJz4gc3RydWN0IGVlcnRyZWUgewogIGVlcnRyZWUoc2l6ZV90IHEpIHsKICAgIHEgKz0gMjsKICAgIHMgPSBzdHJpbmcocSwgLTEpOwogICAgbGVuID0gdmVjdG9yPGludD4ocSwgMCk7CiAgICB0by5yZXNpemUocSk7CiAgICBsaW5rLnJlc2l6ZShxLCAwKTsKICAgIHBvcy5yZXNpemUocSwgLTEpOwogICAgbGlua1swXSA9IDE7CiAgICBsaW5rWzFdID0gMTsKICAgIGxlblsxXSA9IC0xOwogIH0KCiAgcGFpcjxpbnQsIGludD4gYWRkX2xldHRlcihjaGFyIGMsIGludCBpZCkgewogICAgYyAtPSAnYSc7CiAgICBzW24rK10gPSBjOwogICAgd2hpbGUgKGMgIT0gc1tuIC0gbGVuW2xhc3RdIC0gMl0pCiAgICAgIGxhc3QgPSBsaW5rW2xhc3RdOwoKICAgIGlmICghdG9bbGFzdF1bY10pIHsKICAgICAgaW50IGN1ciA9IHN6Kys7CiAgICAgIGxlbltjdXJdID0gbGVuW2xhc3RdICsgMjsKICAgICAgcG9zW2N1cl0gPSAtMTsKICAgICAgaWYgKGxlbltjdXJdID09IDEpIHsKICAgICAgICBsaW5rW2N1cl0gPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIGludCBwID0gbGlua1tsYXN0XTsKICAgICAgICB3aGlsZSAoYyAhPSBzW24gLSBsZW5bcF0gLSAyXSkKICAgICAgICAgIHAgPSBsaW5rW3BdOwogICAgICAgIGxpbmtbY3VyXSA9IHRvW3BdW2NdOwogICAgICB9CiAgICAgIHRvW2xhc3RdW2NdID0gY3VyOwogICAgfQoKICAgIGxhc3QgPSB0b1tsYXN0XVtjXTsKICAgIGludCB4ID0gcG9zW2xhc3RdOwogICAgcG9zW2xhc3RdID0gaWQgKyAxIC0gbGVuW2xhc3RdOwogICAgaW50IHkgPSBwb3NbbGFzdF07CiAgICByZXR1cm4ge3gsIHl9OwogIH0KCnByaXZhdGU6CiAgdmVjdG9yPGFycmF5PGludCwgc2lnbWE+PiB0bzsKICB2ZWN0b3I8aW50PiBsaW5rOwogIHZlY3RvcjxpbnQ+IGxlbiwgcG9zOwogIHN0cmluZyBzOwogIGludCBuID0gMSwgc3ogPSAyLCBsYXN0ID0gMDsKfTsKCmNvbnN0IGludCBOID0gKGludCkxZTUgKyAxOwoKdm9pZCBzb2x2ZShpbnQgdGMgPSAxKSB7CiAgaW50IG47CiAgY2luID4+IG47CiAgaW50IHE7CiAgY2luID4+IHE7CiAgc3RyaW5nIHU7CiAgYXJyYXk8aW50LCBOPiBsLCByOwogIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICBzdHJpbmcgczsKICAgIGNpbiA+PiBzOwogICAgbFtpXSA9IHUuc2l6ZSgpOwogICAgdSArPSBzOwogICAgdSArPSAnYScgKyAyNzsKICAgIHUgKz0gJ2EnICsgMjg7CiAgICByW2ldID0gdS5zaXplKCkgLSAxOwogIH0KICBwcih1LCBsLCByKTsKICBuID0gdS5zaXplKCk7CiAgdmVjdG9yPE5vZGUgKj4gc2VnKG4pOwogIHZlY3RvcjxWYWx1ZT4gdihuLCAwKTsKICBhdXRvIHBhbHRyZWUgPSBlZXJ0cmVlKG4gKyA1KTsKICBhdXRvIG5vdyA9IGJ1aWxkKDAsIG4sIHYpOwogIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICBhdXRvIFt4LCB5XSA9IHBhbHRyZWUuYWRkX2xldHRlcih1W2ldLCBpKTsKICAgIGlmICh4ICE9IC0xKSB7CiAgICAgIGludCB2YWwgPSBxdWVyeShub3csIDAsIG4sIHgsIHggKyAxKS5zdW07CiAgICAgIG5vdyA9IHVwZGF0ZShub3csIHZhbCAtIDEsIHgsIDAsIG4pOwogICAgfQogICAgaW50IHZhbCA9IHF1ZXJ5KG5vdywgMCwgbiwgeSwgeSArIDEpLnN1bTsKICAgIG5vdyA9IHVwZGF0ZShub3csIHZhbCArIDEsIHksIDAsIG4pOwogICAgc2VnW2ldID0gbm93OwogIH0KICBmb3IgKGludCBpID0gMDsgaSA8IHE7IGkrKykgewogICAgaW50IHgsIHk7CiAgICBjaW4gPj4geCA+PiB5OwogICAgLS14OwogICAgLS15OwogICAgaW50IGxxID0gbFt4XTsKICAgIGludCBycSA9IHJbeV07CiAgICBjb3V0IDw8IHF1ZXJ5KHNlZ1tycV0sIDAsIG4sIGxxLCBycSArIDEpLnN1bSAtIDIgPDwgJ1xuJzsKICAgIGNvdXQuZmx1c2goKTsKICB9CgogIHJldHVybjsKfQoKc2lnbmVkIG1haW4oKSB7CiAgY2luLnRpZSgwKS0+c3luY193aXRoX3N0ZGlvKDApOwoKICBjb3V0IDw8IHNldHByZWNpc2lvbigxNikgPDwgZml4ZWQ7CiAgY2VyciA8PCBzZXRwcmVjaXNpb24oNCkgPDwgZml4ZWQ7CgogIGludCB0YyA9IDE7CiAgLy8gY2luID4+IHRjOwogIGZvciAoaW50IHQgPSAxOyB0IDw9IHRjOyB0KyspIHsKICAgIHNvbHZlKHQpOwogIH0KfQ==