字符串模板
hash:
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define lep( i, l, r ) for ( int i = ( l ); i <= ( r ); ++ i )
#define rep( i, r, l ) for ( int i = ( r ); i >= ( l ); -- i )
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair < int, int > pii;
char _c; bool _f; template < class type > inline void read ( type &x ) {
_f = 0, x = 0;
while ( _c = getchar (), !isdigit ( _c ) ) if ( _c == '-' ) _f = 1;
while ( isdigit ( _c ) ) x = x * 10 + _c - '0', _c = getchar (); if ( _f ) { x = -x; }
}
template < class type > inline void chkmin ( type &x, type y ) { x = ( x <= y ? x : y ); }
template < class type > inline void chkmax ( type &x, type y ) { x = ( x >= y ? x : y ); }
int n, ans;
map < string, bool > mp;
void Solve () {
cin >> n;
while ( n -- ) {
string s;
cin >> s;
if ( !mp[s] ) {
mp[s] = 1;
ans ++;
}
}
cout << ans;
}
signed main () {
#ifdef judge
freopen ( "Code.in", "r", stdin );
freopen ( "Code.out", "w", stdout );
freopen ( "Code.err", "w", stderr );
#endif
Solve ();
return 0;
}
树 hash:
#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N = 55;
int m, n;
int hsh[N][N], len[N], siz[N];
int head[N], tot;
struct Graph {
int to, next;
} edges[N << 1];
void add ( int u, int v ) {
tot ++;
edges[tot].to = v;
edges[tot].next = head[u];
head[u] = tot;
}
int dfs ( int x, int fa ) {
siz[x] = 1;
vector < int > g;
int tmp = 0;
for ( int i = head[x]; i; i = edges[i].next ) {
if ( edges[i].to != fa ) {
g.push_back ( dfs ( edges[i].to, x ) );
siz[x] += siz[edges[i].to];
tmp += siz[edges[i].to];
}
}
sort ( g.begin (), g.end () );
int cnt = 0;
for ( int i = 0; i < g.size (); i ++ ) {
cnt ^= ( g[i] * 1145141 );
}
return cnt + tmp;
}
signed main () {
cin >> m;
for ( int i = 1; i <= m; i ++ ) {
tot = 0;
memset ( head, 0, sizeof ( head ) );
cin >> n;
len[i] = n;
for ( int j = 1; j <= n; j ++ ) {
int fa;
cin >> fa;
if ( fa ) {
add ( fa, j ), add ( j, fa );
}
}
for ( int j = 1; j <= n; j ++ ) {
memset ( siz, 0, sizeof ( siz ) );
hsh[i][j] = dfs ( j, 0 );
}
bool flag = false;
for ( int j = 1; j <= i; j ++ ) {
for ( int k = 1; k <= n; k ++ ) {
for ( int l = 1; l <= len[j]; l ++ ) {
if ( hsh[i][k] == hsh[j][l] ) {
cout << j << '\n';
flag = !flag;
break;
}
}
if ( flag ) {
break;
}
}
if ( flag ) {
break;
}
}
}
return 0;
}
冷知识对于一棵树上的子树同构问题有 \(O(n \log n)\) 严格确定性做法。
KMP:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define lep( i, l, r ) for ( int i = ( l ); i <= ( r ); ++ i )
#define rep( i, r, l ) for ( int i = ( r ); i >= ( l ); -- i )
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair < int, int > pii;
namespace IO{
const int SIZE=1<<21;
static char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=oS+SIZE-1;
int qr;
char qu[55],c;
bool f;
#define getchar() (IO::iS==IO::iT?(IO::iT=(IO::iS=IO::ibuf)+fread(IO::ibuf,1,IO::SIZE,stdin),(IO::iS==IO::iT?EOF:*IO::iS++)):*IO::iS++)
#define putchar(x) *IO::oS++=x,IO::oS==IO::oT?flush():0
#define flush() fwrite(IO::obuf,1,IO::oS-IO::obuf,stdout),IO::oS=IO::obuf
#define puts(x) IO::Puts(x)
template<typename T>
inline void read(T&x){
for(f=1,c=getchar();c<48||c>57;c=getchar())f^=c=='-';
for(x=0;c<=57&&c>=48;c=getchar()) x=(x<<1)+(x<<3)+(c&15);
x=f?x:-x;
}
template<typename T>
inline void write(T x){
if(!x) putchar(48); if(x<0) putchar('-'),x=-x;
while(x) qu[++qr]=x%10^48,x/=10;
while(qr) putchar(qu[qr--]);
}
inline void Puts(const char*s){
for(int i=0;s[i];i++)
putchar(s[i]);
putchar('\n');
}
struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}
using IO::read;
using IO::write;
template < class type > inline void chkmin ( type &x, type y ) { x = ( x <= y ? x : y ); }
template < class type > inline void chkmax ( type &x, type y ) { x = ( x >= y ? x : y ); }
const int N = 1e6 + 5;
int n, m;
int nxt[N];
string s, t;
void Solve () {
cin >> s >> t;
n = s.size (), m = t.size ();
s = " " + s, t = " " + t;
for ( int i = 2, j = 0; i <= m; i ++ ) {
while ( j && t[i] != t[j + 1] ) {
j = nxt[j];
}
if ( t[i] == t[j + 1] ) {
j ++;
}
nxt[i] = j;
}
for ( int i = 0, j = 0; i <= n; i ++ ) {
while ( j && s[i] != t[j + 1] ) {
j = nxt[j];
}
if ( s[i] == t[j + 1] ) {
j ++;
}
if ( j == m ) {
cout << i - m + 1 << '\n';
j = nxt[j];
}
}
for ( int i = 1; i <= m; i ++ ) {
cout << nxt[i] << " ";
}
}
signed main () {
#ifdef judge
freopen ( "Code.in", "r", stdin );
freopen ( "Code.out", "w", stdout );
freopen ( "Code.err", "w", stderr );
#endif
Solve ();
return 0;
}
exKMP:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e7 + 5;
int n, m, ans1, ans2;
int z[N], p[N];
string s, t;
signed main () {
ios :: sync_with_stdio ( false );
cin.tie ( 0 ), cout.tie ( 0 );
cin >> s >> t;
n = s.size (), m = t.size ();
s = " " + s, t = " " + t;
z[1] = m;
for ( int i = 2, l = 0, r = 0; i <= m; i ++ ) {
if ( i <= r ) {
z[i] = min ( z[i - l + 1], r - i + 1 );
}
while ( i + z[i] <= m && t[i + z[i]] == t[z[i] + 1] ) {
z[i] ++;
}
if ( i + z[i] - 1 > r ) {
l = i, r = i + z[i] - 1;
}
}
for ( int i = 1, l = 0, r = 0; i <= n; i ++ ) {
if ( i <= r ) {
p[i] = min ( z[i - l + 1], r - i + 1 );
}
while ( i + p[i] <= n && s[i + p[i]] == t[p[i] + 1] ) {
p[i] ++;
}
if ( i + p[i] - 1 > r ) {
l = i, r = i + p[i] - 1;
}
}
for ( int i = 1; i <= m; i ++ ) {
ans1 ^= i * ( z[i] + 1 );
}
for ( int i = 1; i <= n; i ++ ) {
ans2 ^= i * ( p[i] + 1 );
}
cout << ans1 << '\n' << ans2;
return 0;
}
AC 自动机:
#include<bits/stdc++.h>
#define endl '\n';
using namespace std;
const int N = 2e5 + 5;
const int M = 2e6 + 5;
int n;
string s[N], t;
string em;
struct trie{
int fail;
int ch[26];
int cnt;
}ac[N];
int ans[N], val[N];
int tot = 0;
void insert(string s, int id){
int x = 0;
for(int i = 0; i < s.size(); i++){
if(!ac[x].ch[s[i] - 'a']){
ac[x].ch[s[i] - 'a'] = ++tot;
}
x = ac[x].ch[s[i] - 'a'];
}
ac[x].cnt++;
ans[id] = x;
// num[id]
}
int head, tail;
int q[M];
void get_fail(){
for(int i = 0; i < 26; i++){
if(ac[0].ch[i]){
ac[ac[0].ch[i]].fail = 0;
q[tail ++] = ac[0].ch[i];
}
}
while(head < tail){
int x = q[head ++];
for(int i = 0; i < 26; i++){
if(ac[x].ch[i]){
ac[ac[x].ch[i]].fail = ac[ac[x].fail].ch[i];
q[tail ++] = ac[x].ch[i];
}
else{
ac[x].ch[i] = ac[ac[x].fail].ch[i];
}
}
}
}
void query(string s){
int x = 0;
for ( int i = 0; i < s.size (); i ++ ) {
x = ac[x].ch[s[i] - 'a'];
val[x] ++;
}
while ( tail -- ) {
val[ac[q[tail]].fail] += val[q[tail]];
}
}
void Solve(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++){
cin >> s[i];
insert(s[i], i);
}
ac[0].fail = 0;
get_fail();
cin >> t;
query(t);
for ( int i = 1; i <= n; i ++ ) {
cout << val[ans[i]] << '\n';
}
}
signed main(){
Solve();
return 0;
}
SA:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 5;
const int M = 1e6;
int n;
int sa[N << 1], cnt[N << 1], id[N], rk[N << 1], ork[N << 1], h[N];
string s;
signed main () {
ios :: sync_with_stdio ( false );
cin.tie ( 0 ), cout.tie ( 0 );
cin >> s;
n = s.size ();
s = " " + s;
for ( int i = 1; i <= n; i ++ ) rk[i] = s[i], sa[i] = i;
for ( int len = 1; len < n; len <<= 1 ) {
memset ( cnt, 0, sizeof ( cnt ) );
for ( int i = 1; i <= n; i ++ ) id[i] = sa[i];
for ( int i = 1; i <= n; i ++ ) ++ cnt[rk[id[i] + len]];
for ( int i = 1; i <= M; i ++ ) cnt[i] += cnt[i - 1];
for ( int i = n; i >= 1; i -- ) sa[cnt[rk[id[i] + len]] --] = id[i];
memset ( cnt, 0, sizeof ( cnt ) );
for ( int i = 1; i <= n; i ++ ) id[i] = sa[i];
for ( int i = 1; i <= n; i ++ ) ++ cnt[rk[id[i]]];
for ( int i = 1; i <= M; i ++ ) cnt[i] += cnt[i - 1];
for ( int i = n; i >= 1; i -- ) sa[cnt[rk[id[i]]] --] = id[i];
for ( int i = 1; i <= n; i ++ ) ork[i] = rk[i];
int r = 0;
for ( int i = 1; i <= n; i ++ ) {
if ( ork[sa[i]] == ork[sa[i - 1]] && ork[sa[i] + len] == ork[sa[i - 1] + len] ) rk[sa[i]] = r;
else rk[sa[i]] = ++ r;
}
}
int pos = 0;
for ( int i = 1; i <= n; i ++ ) {
if ( pos ) pos --;
while ( s[i + pos] == s[sa[rk[i] - 1] + pos] ) pos ++;
h[rk[i]] = pos;
}
for ( int i = 1; i <= n; i ++ ) {
cout << sa[i] << " ";
}
return 0;
}
SAM:
#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define lep( i, l, r ) for ( int i = ( l ); i <= ( r ); ++ i )
#define rep( i, r, l ) for ( int i = ( r ); i >= ( l ); -- i )
typedef long long ll;
typedef long double ld;
typedef pair < int, int > pii;
char _c; bool _f; template < class type > inline void read ( type &x ) {
_f = 0, x = 0;
while ( _c = getchar (), !isdigit ( _c ) ) if ( _c == '-' ) _f = 1;
while ( isdigit ( _c ) ) x = x * 10 + _c - '0', _c = getchar (); if ( _f ) { x = -x; }
}
template < class type > inline void chkmin ( type &x, type y ) { x = ( x <= y ? x : y ); }
template < class type > inline void chkmax ( type &x, type y ) { x = ( x >= y ? x : y ); }
const int N = 2e6 + 5;
long long ans;
string s;
int cnt = 1, last = 1;
int siz[N];
struct SAM {
int ch[26];
int len, dad;
SAM () {
memset ( ch, 0, sizeof ( ch ) );
len = dad = 0;
}
} sam[N];
int head[N], tot;
struct Graph {
int to, next;
} edges[N];
void add ( int u, int v ) {
tot ++;
edges[tot].to = v;
edges[tot].next = head[u];
head[u] = tot;
}
void insert ( int c ) {
int x = last, cur = last = ++ cnt;
siz[cnt] = 1, sam[cur].len = sam[x].len + 1;
for ( ; x && !sam[x].ch[c]; x = sam[x].dad ) {
sam[x].ch[c] = cur;
}
if ( !x ) {
sam[cur].dad = 1;
}
else {
int y = sam[x].ch[c];
if ( sam[y].len == sam[x].len + 1 ) {
sam[cur].dad = y;
}
else {
int up = ++ cnt;
sam[up] = sam[y];
sam[up].len = sam[x].len + 1;
sam[y].dad = sam[cur].dad = up;
for ( ; x && sam[x].ch[c] == y; x = sam[x].dad ) {
sam[x].ch[c] = up;
}
}
}
}
void dfs ( int x ) {
for ( int i = head[x]; i; i = edges[i].next ) {
dfs ( edges[i].to );
siz[x] += siz[edges[i].to];
}
if ( siz[x] != 1 ) {
chkmax ( ans, 1ll * siz[x] * sam[x].len );
}
}
void Solve () {
cin >> s;
for ( int i = 0; i < s.size (); i ++ ) {
insert ( s[i] - 'a' );
}
for ( int i = 2; i <= cnt; i ++ ) {
add ( sam[i].dad, i );
}
siz[1] = 1;
dfs ( 1 );
cout << ans;
}
signed main () {
#ifdef judge
freopen ( "Code.in", "r", stdin );
freopen ( "Code.out", "w", stdout );
freopen ( "Code.err", "w", stderr );
#endif
Solve ();
return 0;
}
manacher:
#include<bits/stdc++.h>
#define endl '\n';
using namespace std;
const int N = 2.2e7 + 5;
string s, t;
int n, ans = -1e9, k, r;
int len[N];
void Solve(){
cin >> t;
n = (t.size() << 1) + 1;
s.resize(n + 1);
s[0] = '^';
s[n] = '%';
s[1] = '#';
for (int i = 1; i <= t.size(); i ++) {
s[i << 1] = t[i - 1];
s[i << 1 | 1] = '#';
}
len[1] = 1;
for(int i = 2; i <= n; i++){
if(i <= r){
len[i] = min(r - i + 1, len[(k << 1) - i]);
}
else{
len[i] = 1;
}
while(s[i - len[i]] == s[i + len[i]]){
len[i]++;
}
if(i + len[i] > r){
k = i;
r = i + len[i] - 1;
}
ans = max(ans, len[i] - 1);
}
cout << ans;
}
signed main(){
#ifdef debug
freopen("Code.in", "r", stdin);
freopen("Code.out", "w", stdout);
#endif
Solve();
return 0;
}
后缀树:
基本子串结构:
基本子串字典:
/*
他决定要“格”院子里的竹子。于是他搬了一条凳子坐在院子里,面对着竹子硬想了七天,结果因为头痛而宣告失败。
他决定要“格”金策字符串选讲里面的 Interval Pattern Matching。于是他搬了一份 std 坐在机房里,面对着机房硬想了一天,结果因为 Para 太引荐而宣告失败。
DONT NEVER AROUND . //
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int read()
{
int x=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
return x;
}
void write(int x)
{
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int MAXN=200005,MxLgs=19;
int n,Q;
char str[MAXN];
struct SuffixArray{
struct STtable{
int lgstr[MAXN],f[MxLgs][MAXN];
void init(int *a)
{
for(int i=2;i<=n;++i) lgstr[i]=lgstr[i>>1]+1;
for(int i=1;i<=n;++i) f[0][i]=a[i];
for(int i=1;i<MxLgs;++i) for(int j=1;j+(1<<i)-1<=n;++j) f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
}
int query(int l,int r)
{
int d=lgstr[r-l+1];
return min(f[d][l],f[d][r-(1<<d)+1]);
}
void debug(){for(int i=1;i<=n;++i) for(int j=i;j<=n;++j) write(query(i,j)),putchar(' ');puts("");}
}st;
int sa[MAXN],ht[MAXN],cnt[MAXN],x[MAXN],tmp1[MAXN],rk[MAXN],Sigma;
void MakeSuffix()
{
Sigma=128;
for(int i=1;i<=n;++i) ++cnt[x[i]=str[i]];
for(int i=2;i<=Sigma;++i) cnt[i]+=cnt[i-1];
for(int i=n;i;--i) sa[cnt[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int tmp=0;
for(int i=n-k+1;i<=n;++i) tmp1[++tmp]=i;
for(int i=1;i<=n;++i) if(sa[i]>k) tmp1[++tmp]=sa[i]-k;
for(int i=1;i<=Sigma;++i) cnt[i]=0;
for(int i=1;i<=n;++i) ++cnt[x[i]];
for(int i=2;i<=Sigma;++i) cnt[i]+=cnt[i-1];
for(int i=n;i;--i) sa[cnt[x[tmp1[i]]]--]=tmp1[i],tmp1[i]=0;
swap(x,tmp1);
tmp=1;
x[sa[1]]=1;
for(int i=2;i<=n;++i) x[sa[i]]=(tmp1[sa[i]]==tmp1[sa[i-1]] && tmp1[sa[i]+k]==tmp1[sa[i-1]+k])?tmp:++tmp;
if(tmp==n) break;
Sigma=tmp;
}
}
void MakeHeight()
{
int k=0;
for(int i=1;i<=n;++i) rk[sa[i]]=i;
for(int i=1;i<=n;++i)
{
if(rk[i]==1) continue;
if(k) --k;
int j=sa[rk[i]-1];
while(j+k<=n && i+k<=n && str[i+k]==str[j+k]) ++k;
ht[rk[i]]=k;
}
}
int getLCP(int p,int q)
{
if(p==q) return n-p+1;
p=rk[p],q=rk[q];
return st.query(min(p,q)+1,max(p,q));
}
int compare(int l1,int r1,int l2,int r2)
{
assert(r1-l1==r2-l2);
int len=r1-l1+1,lcp=getLCP(l1,l2);
if(lcp>=len) return 0;
return str[l1+lcp]<str[l2+lcp]?-1:1;
}
void init(){MakeSuffix(),MakeHeight(),st.init(ht);}
void debug(){for(int i=1;i<=n;++i) write(sa[i]),putchar(i==n?'\n':' ');for(int i=1;i<=n;++i) write(rk[i]),putchar(i==n?'\n':' ');for(int i=1;i<=n;++i) write(ht[i]),putchar(i==n?'\n':' ');}
}Sa;
int CmpLen;
bool cmp(int x,int y)
{
int rt=Sa.compare(x,x+CmpLen-1,y,y+CmpLen-1);
if(!rt) return x<y;
return rt<0;
}
namespace IntervalPatternMatching{
struct matchSeq{
int p0,p1,cnt;
matchSeq(){p0=p1=cnt=0;}
matchSeq(int a,int b,int c,int type)
{
if(type==1) p0=p1=a,cnt=1;
else if(type==2) p0=a,p1=b,cnt=1+int(p0!=p1);
else p0=a,p1=b,cnt=c;
}
matchSeq(int *a,int c)
{
if(c<=0)
{
cnt=0;
return ;
}
if(c==1) p0=p1=a[0];
else p0=a[0],p1=a[1],cnt=c;
}
inline bool isContain(int x)
{
if(!cnt) return false;
if(cnt<=2) return (x==p0 || x==p1);
x-=p0;
int d=p1-p0;
return bool(x%d==0 && x/d>=0 && x/d<cnt);
}
inline int getIndex(int x)
{
if(!isContain(x)) return -1;
return (x-p0)/(p1-p0);
}
inline int getVal(int id){return p0+id*(p1-p0);}
inline int getMax(){return getVal(cnt-1);}
matchSeq operator - (){return matchSeq(-p0,-p1,cnt,3);}
matchSeq operator + (int d){return matchSeq(p0+d,p1+d,cnt,3);}
matchSeq operator - (int d){return matchSeq(p0-d,p1-d,cnt,3);}
inline void debug(){printf("%d %d %d\n",p0,p1,cnt);}
};
matchSeq mov(matchSeq seq)
{
if(seq.cnt<=1) return seq;
int q0=seq.getVal(seq.cnt-1),q1=seq.getVal(seq.cnt-2);
return matchSeq(q0,q1,seq.cnt,3);
}
matchSeq merge(matchSeq u,matchSeq v)
{
int tmp[6],cnt=0;
if(!u.cnt || !v.cnt) return matchSeq();
if(u.cnt<3)
{
for(int i=0,x=u.p0,d=u.p1-u.p0;i<u.cnt;++i,x+=d) if(v.isContain(x)) tmp[cnt++]=x;
return matchSeq(tmp,cnt);
}
if(v.cnt<3)
{
for(int i=0,x=v.p0,d=v.p1-v.p0;i<v.cnt;++i,x+=d) if(u.isContain(x)) tmp[cnt++]=x;
return matchSeq(tmp,cnt);
}
assert(u.p1-u.p0==v.p1-v.p0);
int l=u.getIndex(v.p0);
if(l==-1) return matchSeq();
int r=l+v.cnt;
r=min(r,u.cnt);
if(l>=r) return matchSeq();
return matchSeq(u.getVal(l),u.getVal(l+1),r-l,3);
}
int f[MxLgs][MAXN];
void init()
{
Sa.init();
for(int k=0;(1<<k)<=n;++k)
{
CmpLen=(1<<k);
for(int i=1;i+CmpLen<=n+1;++i) f[k][i]=i;
sort(f[k]+1,f[k]+1+(n-CmpLen+1),cmp);
}
}
#define mp make_pair
pair<int,int> getRange(int s,int k)
{
int len=(1<<k),L=-1,R=-1;
int l,r;
l=1,r=n-len+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(Sa.compare(s,s+len-1,f[k][mid],f[k][mid]+len-1)>0) l=mid+1;
else r=(L=mid)-1;
}
l=1,r=n-len+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(Sa.compare(s,s+len-1,f[k][mid],f[k][mid]+len-1)>=0) l=(R=mid)+1;
else r=mid-1;
}
return mp(L,R);
}
#undef mp
int succ(int s,int k,int i,int L,int R)
{
if(L>R) return MAXN*2;
int l=L,r=R,ans=R+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(f[k][mid]>=i) r=(ans=mid)-1;
else l=mid+1;
}
if(ans>R) return MAXN*2;
return f[k][ans];
}
int pred(int s,int k,int i)
{
int L,R;
pair<int,int> tmp=getRange(s,k);
L=tmp.first,R=tmp.second;
if(L>R) return -MAXN;
int l=L,r=R,ans=L-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(f[k][mid]<=i) l=(ans=mid)+1;
else r=mid-1;
}
if(ans<L) return -MAXN;
return f[k][ans];
}
matchSeq query(int l,int r,int s,int k)
{
int len=(1<<k);
pair<int,int> tmp=getRange(s,k);
int L=tmp.first,R=tmp.second;
int q0=succ(s,k,l,L,R);
if(q0+len-1>r) return matchSeq();
int q1=succ(s,k,q0+1,L,R);
if(q1+len-1>r) return matchSeq(q0,q0,1,1);
int qx=pred(s,k,r-len+1);
matchSeq ret=matchSeq(q0,q1,MAXN,3);
ret.cnt=ret.getIndex(qx)+1;
return ret;
}
void debug(){for(int i=0;i<MxLgs;++i,puts("")) for(int j=1;j<=n;++j) printf("%d ",f[i][j]);puts("");}
}
#define IPM IntervalPatternMatching
int query(int l,int r)
{
int Slen=(r-l+2)/2,lim=0;
while((1<<lim)<Slen) ++lim;
for(int i=lim;~i;--i)
{
int len=min(r-l,1<<(i+1)),slen=(1<<i);
IPM::matchSeq st1=IPM::query(l,l+len-1,r-slen+1,i),st2=IPM::query(r-len+1,r,l,i);
st1=st1-l+slen;
st2=-IPM::mov(st2)+r+1;
st1=IPM::merge(st1,st2);
if(st1.cnt) return st1.getMax();
}
return int(str[l]==str[r] && (l^r));
}
int main(){
scanf("%s",str+1),n=strlen(str+1);
IPM::init();
Q=read();
while(Q-->0)
{
int l=read(),r=read();
write(query(l,r)),puts("");
}
return 0;
}

浙公网安备 33010602011771号