Loading

字符串模板

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;
}

posted @ 2025-12-22 17:30  Alexande  阅读(7)  评论(0)    收藏  举报