#include <bits/stdc++.h>
#define rep(i, l, r) for(int i = (l); i <= (r); i++)
#define rge(i, l, r) for(int i = (l); i < (r); i++)
#define forn(i, n) rep(i, 1, n)
#define forr(i, n) rge(i, 0, n)
#define rept(i, l, r) for(T i = (l); i <= (r); i++) /* tag : definatiors */
#define rget(i, l, r) for(T i = (l); i < (r); i++) /* tag : definatiors */
#define fornt(i, n) rept(i, 1, n) /* tag : definatiors */
#define forrt(i, n) rget(i, 0, n) /* tag : definatiors */
#define al(item) (item).begin(), (item).end()
#define se second
#define pb push_back
#define nxtp next_permutation
#define int long long /* tag : warning */
#define int32 int
#define int64 long long
#define int128 __int128
#define db double
#define ld long double
#define fi first
#define exitcode(x) { cout << x << endl; return 0; }
using namespace std;

/* rander */ namespace rander {
//rand values
//based on mt19937
unsigned long long seed = chrono::system_clock::now().time_since_epoch().count();
mt19937 rd(seed);
int randint(int l, int r) {
    uniform_int_distribution<int> lim(l, r);
    return lim(rd);
}
long long randlong(long long l, long long r) {
    uniform_int_distribution<long long> lim(l, r);
    return lim(rd);
}
vector<int> permutation_shuffle(int size_) {
    vector<int> ans(size_ + 10);

    for (int i = 1; i <= size_; i++) {
        ans[i - 1] = i;
    }

    for (int i = 1; i <= size_ * ((int)log(size_)); i++) {
        int leftcur = randint(1, size_);
        int rightcur = randint(1, size_);
        swap(ans[leftcur - 1], ans[rightcur - 1]);
    }

    ans.resize(size_ + 1);
    return ans;
}
vector<int> common_shuffle(vector<int> v) {
    int size_ = v.size();
    vector<int> ans = v;

    for (int i = 1; i <= size_; i++) {
        ans[i - 1] = v[i - 1];
    }

    for (int i = 1; i <= size_ * ((int)log(size_)); i++) {
        int leftcur = randint(1, size_);
        int rightcur = randint(1, size_);
        swap(ans[leftcur - 1], ans[rightcur - 1]);
    }

    ans.resize(size_ + 1);
    return ans;
}
vector<int> array_random(int size_, int l, int r) {
    vector<int> ans(size_ + 10);

    for (int i = 1; i <= size_; i++) {
        ans[i - 1] = randint(l, r);
    }

    ans.resize(size_ + 1);
    return ans;
}
vector<int> random_sorted(int size_, int l, int r) {
    vector<int> ans = array_random(size_, l, r);
    sort(ans.begin(), ans.end());
    return ans;
}
vector<int> random_unique(int size_, int l, int r) {
    vector<int> ans = random_sorted(size_, l, r);
    unique(ans.begin(), ans.end());
    ans = common_shuffle(ans);
    return ans;
}
}

using namespace rander;

/* Fast IO */ namespace FastIO {
template<typename T> inline T read() {
    T x = 0, w = 1;
    char c = 0;

    while (c < '0' || c > '9') {
        if (c == '-')
            w = -1;

        c = getchar();
    }

    while (c >= '0' && c <= '9') {
        x = x * 10 + (c - '0');
        c = getchar();
    }

    return x * w;
}
template <typename T> inline void write(T x) {
    if (x < 0) {
        x = -x;
        putchar('-');
    }

    if (x > 9)
        write(x / 10);

    putchar(x % 10 + '0');
}
int getInt() {
	return read<int>();
}
void putInt(int x, char c) {
	write<int>(x), putchar(c);
	return ;
}
} using namespace FastIO;

/* combinatorics */ namespace combinatorics {
int mod = 998244353;
template<typename T> inline T qpow(T a, T b, T p) {
    T res = 1;

    while (b) {
        if (b % 2 == 1)
            res = res * a % p;

        a = a * a % p;
        b /= 2;
    }

    return res;
}
template<typename T> struct factorial {
    T fac[1000005], ifac[1000005];
    T d[1000005], cat[1000005];

    inline void init(T lim) {
        fac[0] = ifac[0] = d[0] = cat[0] = 1;
        ifac[lim] = qpow<T>(fac[lim], mod - 2, mod);
        rept(i, 1, lim) fac[i] = fac[i - 1] * i % mod;
        rept(i, 2, lim) d[i] = (d[i - 1] + d[i - 2]) * (i - 1) % mod;

        for (T i = lim - 1; i; i--)
            ifac[i] = ifac[i + 1] * (i + 1) % mod;

        rept(i, 1, lim) cat[i] = cat[i - 1] * (4 * i - 2) * qpow<T>(i + 1, mod - 2, mod);
    }

    inline T C(T n, T k, T p) {
        return fac[n] * qpow<T>(fac[k], mod - 2, mod) % mod * qpow<T>(fac[n - k], mod - 2, mod) % mod;
    }
};
} using namespace combinatorics;

/* union find set */ struct ufs {
    int fa[1000005];

    inline void init(int n) {
        rep(i, 1, n) fa[i] = i;
    } inline int find(int x) {
        return (fa[x] == x ? x : (fa[x] = find(fa[x])));
    } void unite(int x, int y) {
        if (find(x) != find(y))
            fa[find(x)] = find(y);
    } bool together(int x, int y) {
        return find(x) == find(y);
    }
};

/* definations */

/* Temp Main Func */ int solve() {
	factorial<int> f;
	f.init(100005);
	int n = getInt(), k = min(getInt(), n);
	int s = 0;
	for(int i = 0; i <= k; i++)
	s += f.C(n, i, 1000000007);
	cout << s << endl;
    return 0;
}

/* Main Func */ signed main() {
    int _T_ = read<int>();

    while (_T_--)
        solve();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
int n , t;
cin >> n >> t;
if(n==1&&t==10){
cout << -1;
return 0;
}
    cout << t;

for(int i=1;i<n;i++){
    cout << t;
}

cout << endl;
}


#include<bits/stdc++.h>
using namespace std;
 int main()
 {int n,t;
 cin>>n>>t;
 if(t==10){cout<<"-1"; return 0;
 }else
 {for(int i=0;i<n;i++)
 cout<<t;
 }

}


#include <iostream>
#include <conio.h>
#include <math.h>
using namespace std;
main()
{
    int n,t,b=0;
    cin>>n;
    int a1=pow(10,n-1),a2=pow(10,n);
    cin>>t;
    for (int i=a1+1;i<a2+1;i++)
    {

        if(i%t==0)
        {

            b=i;
            break;
        }

    }
    if(b==0)    cout<<"-1";
    else        cout<<b;

	getch();
	return(0);
}


#include<cstdio>
#include<iostream>
#include<conio.h>
using namespace std;
int main()
{
    int a,t;
    cin>>a>>t;
    if(a>=2)
    {
            cout<<"1";
            for(int i=1;i<a-1;i++)
            {
                    cout<<"0";
            }
            if(t==2||t==3||t==6)
            {
                        cout<<"2"<<endl;
            }
            else if(t==5||t==10||t==4)
            {
                 cout<<"0"<<endl;
            }
            else if(t==7)
            {
                 cout<<"5"<<endl;
            }
            else if(t==8)
            {
                 cout<<"4"<<endl;
            }
            else if(t==9)
            {
                 cout<<"8"<<endl;
            }
    }
    else if(a==1)
    {
            cout<<t<<endl;
    }
    getch();
}


#ifndef ONLINE_JUDGE
#include "Akshat.hpp"
#else
#include "bits/stdc++.h"
using namespace std;
#define dbg(...)
#define debug(...)
#endif

// ----------------------------<optimizations>----------------------------
/*
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx,avx2,fma")
*/
// ---------------------------</optimizations>----------------------------

// ---------------------------------<PBDS>--------------------------------
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <class T>
using o_set = __gnu_pbds::tree<T, __gnu_pbds::null_type, std::less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class T>
using o_multiset = __gnu_pbds::tree<T, __gnu_pbds::null_type, std::less_equal<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class key, class value, class cmp = std::less<key>>
using o_map = __gnu_pbds::tree<key, value, cmp, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
//member functions :
// 1. order_of_key (val): returns the no. of values less than val
// 2. find_by_order (k): returns the iterator to kth largest element.(0-based)
// for ordered_multiset, lower_bound and upper_bound swap roles
// --------------------------------</PBDS>--------------------------------

// -------------------------<Defines and typedefs>------------------------
using ll = int64_t;
using db = double;
using str = string;
using ull = unsigned long long;
#define fo(i, n) for (ll i = 0; i < n; i++)
#define rep(i, k, n) for (ll i = k; k < n ? i < n : i > n; k < n ? i++ : i--)
#define set_bits(x) __builtin_popcountll(x)
#define eb emplace_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
#define uniq(x) (x).erase(unique(all(x)), (x).end())
#define rall(x) (x).rbegin(), (x).rend()
#define ps(x, y) fixed << setprecision(y) << x
#define tr(it, a) for (auto it = a.begin(); it != a.end(); it++)
#define sz(x) ((ll)(x).size())
template <class T>
using V = vector<T>;
using vl = V<ll>;
using vvl = V<vl>;
template <class T, class U = T>
using P = pair<T, U>;
using pl = P<ll, ll>;
using vpl = V<pl>;
// ------------------------</Defines and typedefs>------------------------

// --------------------------------<Consts>-------------------------------
const ll mod = 1e9 + 7;  //1000000007
const ll mod2 = 998244353;
const ll inf = LLONG_MAX;
const db eps = 1e-12;
const double PI = acos(-1);
// -------------------------------</Consts>-------------------------------

// -------------------------------<Templates>-----------------------------
template <class T, class U = T>
bool amin(T& a, U&& b) {
    return b < a ? a = std::forward<U>(b), true : false;
}
template <class T, class U = T>
bool amax(T& a, U&& b) {
    return a < b ? a = std::forward<U>(b), true : false;
}
// ------------------------------</Templates>-----------------------------

// ---------------------------------<Solve>-------------------------------

ll num(string s) {
    ll res = 0;
    for (ll i = 0; i < (ll)s.size(); ++i) {
        res = res * 10 + (s[i] - '0');
    }
    return res;
}

void Solution() {
    string s;
    cin >> s;
    ll n = s.length();
    if (s == "0" || s == "X" || s == "_") return void(cout << 1);
    if (n == 1) return void(cout << 0);
    // now n >= 2 && n <= 8
    string bak = s.substr(n - 2);
    string frnt = s.substr(0, n - 2);

    ll ans = 1;
    fo(i, sz(frnt)) {
        if (s[i] == '_') {
            if (i == 0)
                ans *= 9;
            else
                ans *= 10;
        }
    }
    ll it = frnt.find('X');
    bool yes_f = (it == 0);
    bool yes = (it != -1);
    bool no = (it == -1);
    bool nothin = (frnt == "");
    dbg(ans);

    // 25 75 50 00
    if (bak == "__") {
        if (nothin)
            ans *= 3;
        else {
            ans *= 4;
            if (yes_f)
                ans *= 9;
            else if (yes)
                ans *= 10;
        }
        cout << ans;
    } else if (bak == "_X") {
        if (nothin)
            ans *= 3;
        else {
            ans *= 2;
            if (yes_f)
                ans *= 1;
            else if (yes || no)
                ans *= 2;
        }
        cout << ans;
    } else if (bak == "X_") {
        if (nothin)
            ans *= 3;
        else {
            if (yes_f)
                ans *= 3;  //25 75 50
            else if (yes || no)
                ans *= 4;
        }
        cout << ans;
    } else if (bak == "XX") {
        if (nothin)
            ans = 0;
        else {
            // so XX can be 00
            if (yes_f)
                ans = 0;
            else if (yes || no) {
            }
        }
        cout << ans;
    } else if (bak[0] == '_') {
        if (yes_f)
            ans *= 9;
        else if (yes)
            ans *= 10;
        if (bak[1] == '5') {
            ans *= 2;  //25 75
            cout << ans;
        } else if (bak[1] == '0') {
            if (nothin) {
            } else
                ans *= 2;  // 00 50
            cout << ans;
        } else {
            cout << 0;
        }
    } else if (bak[1] == '_') {
        if (it == 0)
            ans *= 9;
        else if (it != -1)
            ans *= 10;  // Xs in frnt
        if (bak[0] == '2') {
            cout << ans;  // 2_
        }
        if (bak[0] == '5') {
            cout << ans;  //5_
        }
        if (bak[0] == '7') {
            cout << ans;  //7_
        }
        if (bak[0] == '0') {
            //0_, this frnt cant be empty
            cout << ans;
        } else
            cout << 0;
    } else if (bak[0] == 'X') {
        if (bak[1] == '0') {  // X0
            if (it == 0)
                cout << ans;
            else if (it != -1)
                cout << 2 * ans;
            else if (it == -1)
                cout << 1;
        }
        if (bak[1] == '5') {  // X5
            ans *= 2;         // bcoz of X
            cout << ans;
        }
    } else if (bak[1] == 'X') {
        if (bak[0] == '2' || bak[0] == '7') {
            // 2X
            cout << ans;
        }
        if (bak[0] == '5') {
            // 5X
            if (yes_f) ans = 0;
            cout << ans;
        }
        if (bak[0] == '0') {
            // 0X now as frnt cant be empty
            if (yes_f) ans = 0;
            cout << ans;
        }
    } else if (bak == "25" || bak == "75" || bak == "50" || bak == "00") {
        if (yes_f)
            ans *= 9;
        else if (yes)
            ans *= 10;
        cout << ans;
    } else
        cout << 0;
    cout << '\n';
}

/*
10
_X8_
X_X_
____
XXXX
X000
X_XX
__X5
_X58
9090
2050
*/

// --------------------------------</Solve>-------------------------------

int main() {
    ll tc = 1;
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    cin.tie(nullptr)->sync_with_stdio(false);
#ifdef NCR
    init();
#endif
    // cin >> tc;
    while (tc--) {
        Solution();
    }
#ifndef ONLINE_JUDGE
    cerr << fixed << setprecision(4) << (double)clock() / CLOCKS_PER_SEC << " secs" << endl;
#endif
    return 0;
}

/*
    ? Stuff to look for ->
    * stay organised
    * int overflows, array bounds, etc.
    * special cases (n=1)?
    * do something instead of nothing
    * n % mod = (n % mod + mod) % mod; (Handling negatives)
    * When using a set, lower_bound(all(set),l) is slower than set.lower_bound(l) because of random iterators
    * string .append() or += is O1, but s = s + s is On (as it creates a copy first), use wisely
    * DONT GET STUCK ON ONE APPROACH
    * use __lg(n) instead of log2(n), int: 32 - __builtin_clz(n), ll: 63 - __builtin_clzll(n), https://codeforces.com/blog/entry/45966
    * string.rfind() finds first occurence from end
    * (a & b) + (a | b) = a + b
    * TLE due to ll ? or multiple copies of large DS?
    * didnt use inv() in modular combinatorics?
*/


#include <algorithm>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_map>
#include <vector>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define lowbit(x) (x & -x)
#define fi first
#define se second
#define Size(a) int((a).size())
#define all(x) x.begin(), x.end()
#define ull unsigned long long
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define endl "\n"
#define bug cout << "----acac----" << endl;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;
ll ksm(ll a, ll b, ll mod)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1)
        {
            ans = (a % mod * ans % mod) % mod;
        }
        b >>= 1;
        a = (a % mod * a % mod) % mod;
    }
    return ans;
}
ll gcd(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}
ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
const ll mod = 998244353;
const int maxn = 2e6 + 10;
const int N = 2e5 + 10;
const int maxm = 2e3 + 50;
const double eps = 1e-8;
const ll inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1);
int ans;
map<string, int> p;
vector<int> v;
int vis[100];
void dfs(string s, int cnt, int sum)
{
    if ((s[0] == '0' && s.size() != 1) || p[s])
    {
        return;
    }
    //cout << cnt <<" "<<s.size()<< endl;
    if (cnt == (int)s.size())
    {
        //cout << s << " " << sum << endl;
        ans += (sum == 0);
        return;
    }
    if (s[cnt] == '_')
    {
        for (int j = 0; j < 10; j++)
        {
            s[cnt] = '0' + j;
            dfs(s, cnt + 1, (sum * 10 + j) % 25);
        }
    }
    else
    {
        dfs(s, cnt + 1, (sum * 10 + (s[cnt] - '0')) % 25);
    }
}
string s;
int main()
{
    ans = 0;
    cin >> s;
    if (s.size() == 1 && s[0] == '0')
    {
        cout << "1" << endl;
        return 0;
    }
    for (int i = 0; i < (int)s.size(); i++)
    {
        if (s[i] == 'X')
        {
            for (int j = 0; j < 10; j++)
            {
                string s0 = s;
                for (int k = 0; k < (int)s.size(); k++)
                {
                    if (s0[k] == 'X')
                    {
                        s0[k] = j + '0';
                    }
                }
                dfs(s0, 0, 0);
            }
            cout << ans << endl;
            return 0;
        }
    }
    dfs(s, 0, 0);
    cout << ans << endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

#define ll 		long long
#define all(v)		v.begin(), v.end()
#define DEBUG(x) 	std::cout << #x << " = " << x << "\n"
#define FOR(i, a, b)	for(ll i=a; i<=b; i++)

const ll MOD = 1e9 + 7;

#define MOD_ADD(a, b)	(a%MOD + b%MOD)%MOD
#define MOD_MUL(a, b)	(a%MOD * b%MOD)%MOD
#define MOD_DIV(a, b)	(a%MOD * xpow(b, MOD-2))%MOD

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

ll xpow(ll a, ll b){if(b==0)	return 1;ll aa = xpow(a, b/2);aa %= MOD;aa = (aa*aa)%MOD;if(b&1){aa*= a;aa %= MOD;}	return aa;}

vector<string>pos;

void recur(string s, ll idx, ll c){

	if(c==0){

		pos.push_back(s);

		return;
	}

	if(s[idx]!='_')	recur(s, idx+1, c);
	else{
		FOR(i, 0, 9){
			auto ss = s;
			ss[idx] = '0' + i;
			recur(ss, idx+1, c-1);
		}
	}

}

void solve(){
	string s;	cin>>s;
	set<string>e;
	e.insert("00");
	e.insert("25");
	e.insert("50");
	e.insert("75");

	ll cx = 0;
	for(auto x:s)	if(x=='X')	cx++;

	ll c_ = 0;
	for(auto x:s)	if(x=='_')	c_++;

	ll ans = 0;

	recur(s, 0, c_);

	// cout<<"====== pos ======\n";
	// for(auto x:pos)	cout<<x<<endl;

	if(cx==0){
		for(auto &xp:pos){
			auto ss = xp;

			if(ss.length()==1)	ans += ss[0]=='0';
			else{
				if(ss[0]=='0')	continue;

				string l;
				l += ss[ss.length()-2];
				l += ss[ss.length()-1];

				ans += e.count(l);
			}
		}
	}else{
		FOR(i, 0, 9){
			for(auto &xp:pos){
				auto ss = xp;
				// cout<<ss<<endl;
				for(auto &x:ss)	if(x=='X')	x='0'+i;
				// cout<<ss<<endl;

				if(ss.length()==1)	ans += ss[0]=='0';
				else{
					if(ss[0]=='0')	continue;

					string l;
					l += ss[ss.length()-2];
					l += ss[ss.length()-1];

					ans += e.count(l);
				}
			}
		}
	}

	cout<<ans<<endl;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	// ll t;	cin>>t;
	// while(t--)
		solve();

	return 0;
}


/* author :- _thor__ (Piyush Gupta)*/

#include"bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pbds                                               \
    tree<pair<int, int>, null_type, less<pair<int, int> >, \
         rb_tree_tag, tree_order_statistics_node_update>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
using namespace std;
#define _thor__ ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define MOD 1000000007
#define MOD1 998244353
#define INF LLONG_MAX
#define VI(n) vector<ll>a(n);
#define endl "\n"
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define ff first
#define ss second
#define PI 3.141592653589793238462
#define set_bits __builtin_popcountll
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()

typedef long long ll;
typedef unsigned long long ull;
typedef long double lld;
// typedef tree<pair<int, int>, null_type, less<pair<int, int>>, rb_tree_tag, tree_order_statistics_node_update > pbds; // find_by_order, order_of_key

#ifndef ONLINE_JUDGE
#define debug(x) cerr << #x <<" "; _print(x); cerr << endl;
#else
#define debug(x)
#endif

void _print(ll t) {cerr << t;}
void _print(int t) {cerr << t;}
void _print(string t) {cerr << t;}
void _print(char t) {cerr << t;}
void _print(lld t) {cerr << t;}
void _print(double t) {cerr << t;}
void _print(ull t) {cerr << t;}

template <class T, class V> void _print(pair <T, V> p);
template <class T> void _print(vector <T> v);
template <class T> void _print(set <T> v);
template <class T, class V> void _print(map <T, V> v);
template <class T> void _print(multiset <T> v);
template <class T, class V> void _print(pair <T, V> p) {cerr << "{"; _print(p.ff); cerr << ","; _print(p.ss); cerr << "}";}
template <class T> void _print(vector <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(set <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(multiset <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T, class V> void _print(map <T, V> v) {cerr << "[ "; for (auto i : v) {_print(i); cerr << " ";} cerr << "]";}
/****************************************************************************************************************************/
ll gcd(ll a, ll b) {if (b > a) {return gcd(b, a);} if (b == 0) {return a;} return gcd(b, a % b);}
ll expo(ll a, ll b, ll mod) {ll res = 1; while (b > 0) {if (b & 1)res = (res * a) % mod; a = (a * a) % mod; b = b >> 1;} return res;}
void extendgcd(ll a, ll b, ll*v) {if (b == 0) {v[0] = 1; v[1] = 0; v[2] = a; return ;} extendgcd(b, a % b, v); ll x = v[1]; v[1] = v[0] - v[1] * (a / b); v[0] = x; return;} //pass an arry of size1 3
ll lcm(ll a,ll b){return (a*b)/gcd(a,b);}
ll countDivisors(ll n){ll cnt = 0;for (ll i = 1; i <= sqrt(n); i++) {if (n % i == 0) {if (n / i == i)cnt++;else cnt = cnt + 2;}}return cnt;}

ll mminv(ll a, ll b) {ll arr[3]; extendgcd(a, b, arr); return arr[0];} //for non prime b
ll mminvprime(ll a, ll b) {return expo(a, b - 2, b);}
bool revsort(ll a, ll b) {return a > b;}
ll combination(ll n, ll r, ll m, ll *fact, ll *ifact) {ll val1 = fact[n]; ll val2 = ifact[n - r]; ll val3 = ifact[r]; return (((val1 * val2) % m) * val3) % m;}
void google(int t) {cout << "Case #" << t << ": ";}
vector<ll> primeFactors(ll n){vector<ll>ret;while (n % 2 == 0){ret.pb(2);n = n/2;}for (ll i = 3; i <= sqrt(n); i = i + 2){while (n % i == 0){ret.pb(i);n = n/i;}}if (n > 2){ret.pb(n);}return ret;}
vector<ll> prime(ll n) {ll*arr = new ll[n + 1](); vector<ll> vect; for (ll i = 2; i <= n; i++)if (arr[i] == 0) {vect.push_back(i); for (ll j = (ll(i) * ll(i)); j <= n; j += i)arr[j] = 1;} return vect;}
vector<ll>divisor(ll n){vector<ll>res;for (ll i=1; i<=sqrt(n); i++){if (n%i == 0){if (n/i == i)res.pb(i);else{res.pb(i);res.pb(n/i);} }}return res;}
vector<ll>sieve(){ll MAXN=1e7;vector<ll>spf(MAXN);spf[1] = 1;for (ll i=2; i<MAXN; i++)spf[i] = i;for (ll i=4; i<MAXN; i+=2)spf[i] = 2;for (ll i=3; i*i<MAXN; i++){if (spf[i] == i){for (ll j=i*i; j<MAXN; j+=i)if (spf[j]==j)spf[j] = i;}}return spf;}
ll countnumber(ll n){ll cnt=0;while(n>0){cnt++;n/=10;}return cnt;}
vector<ll>countSmallerRight(vector<ll>arr){pbds s;ll n = arr.size();vector<ll> ans;for (ll i = n - 1; i >= 0; i--) {if (i == n - 1) { ans.push_back(0);}else {ans.push_back(s.order_of_key({ arr[i], i }));}s.insert({ arr[i], i });}reverse(ans.begin(), ans.end());return ans;}
ll mod_add(ll a, ll b, ll m) {a = a % m; b = b % m; return (((a + b) % m) + m) % m;}
ll getupper(ll k){ll x = 8*k+1;ll sqr = sqrt(x);if((sqr*sqr)==x){sqr--;return(sqr/2);}sqr--;return (sqr/2)+1;}
ll get2upper(ll n,ll rem){ll a = (2*n)+1;ll s = ((4*n*n)+(4*n)+1)-(8*rem);ll sqr = sqrt(s);if((sqr*sqr)==s){return ((a-sqr)/2)-1;}sqr++;return ((a-sqr)/2);}
ll mod_mul(ll a, ll b, ll m) {a = a % m; b = b % m; return (((a * b) % m) + m) % m;}
ll mod_sub(ll a, ll b, ll m) {a = a % m; b = b % m; return (((a - b) % m) + m) % m;}
ll cei(vector<ll>&v,ll l,ll r,ll key){while (r - l > 1) {ll m = l + (r - l) / 2;if (v[m] > key)r = m;else l = m;}return r;}
ll LongestIS(vector<ll>& v){if (v.size() == 0)return 0;vector<ll> tail(v.size(), 0);ll length = 1; tail[0] = v[0];for (size_t i = 1; i < v.size(); i++) {if (v[i] < tail[0])tail[0] = v[i];else if (v[i] >= tail[length - 1])tail[length++] = v[i];else tail[cei(tail, -1, length - 1, v[i])] = v[i];}return length;}
ll mod_div(ll a, ll b, ll m) {a = a % m; b = b % m; return (mod_mul(a, mminvprime(b, m), m) + m) % m;}  //only for prime m
vector<ll>factorial(ll n,ll m){vector<ll>v(n);v[0]=1;for(ll i=1;i<n;i++){v[i]=mod_mul(v[i-1],i,m);}return v;}
ll nCr(ll n, ll r, vector<ll>&fact,ll m) {ll a = fact[n];ll b = fact[n-r];ll c = fact[r];ll ans1 = mod_mul(b,c,m);ans1 = mod_div(a,ans1,m);return ans1;}
ll modPower(ll x,ll y){ll res = 1;x = x % MOD;if (x == 0)return 0;while (y > 0) {if (y & 1)res = (res * x) % MOD;y = y / 2;x = (x * x) % MOD;}return res;}
ll phin(ll n) {ll number = n; if (n % 2 == 0) {number /= 2; while (n % 2 == 0) n /= 2;} for (ll i = 3; i <= sqrt(n); i += 2) {if (n % i == 0) {while (n % i == 0)n /= i; number = (number / i * (i - 1));}} if (n > 1)number = (number / n * (n - 1)) ; return number;} //O(sqrt(N))
ll modFact(ll n){if (n >= MOD)return 0;ll result = 1;for (ll i = 1; i <= n; i++)result = (result * i) % MOD;return result;}
ll power(ll x,ll y){ll res=1;while(y>0){if(y&1)res = res * x;y = y >> 1;x = x * x;}return res;}
ll negMOD(ll x){x=-x;ll s = x/MOD;if(x%MOD)s++;return (MOD*s)-x;}
void precision(ll a) {cout << setprecision(a) << fixed;}
/*prime-O(n*log(log(n)));
 smallest prime factor-O(log(n));
 a%(b+c)=0 <=> a%c = b%c */
/*--------------------------------------------------------------------------------------------------------------------------*/
const int N = 1e5+25;
vector<string>v;
void re(string &s,ll i)
{
  if(i<0)
  {
    v.pb(s);
    return;
  }

  if(s[i]=='_')
  {
    for(ll j=0;j<10;j++)
    {
      s[i]=j+'0';
      re(s,i-1);
      s[i]='_';
    }
  }
  else re(s,i-1);
}
bool yes(string &s)
{
  // debug(s)
  if(sz(s)==1&&s=="0")return true;
  if(sz(s)>1&&s[0]=='0')return false;
  ll x = stoi(s);
  if(x%25==0)return true;
  return false;
}
void solve()
{
  string s; cin>>s;
  ll n = sz(s);

  re(s,n-1);
  debug(v)
  // cout<<sz(v);
  ll res=0;
  for(ll i=0;i<sz(v);i++)
  {
    string t = v[i];
    if(count(all(t),'X'))
    {
      for(ll j=0;j<10;j++)
      {
        string x=t;
        for(ll k=0;k<sz(t);k++)
        {
          if(t[k]=='X')t[k]=j+'0';
        }
        // debug(t)
        if(yes(t))res++;
        t=x;
      }
    }
    else{
      if(yes(t))res++;
    }
  }
  cout<<res<<endl;

}
int main()
{
  #ifndef ONLINE_JUDGE
    freopen("Error.txt", "w", stderr);
  #endif

    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    _thor__;
    // se();
    // ll test; cin>>test; while(test--) {solve();}
    solve();
  return 0;

}


#include <iostream>
#include <string>
//#include <conio.h>

using namespace std;

int main()
{
    string s;
    cin>>s;
    float a=((int)s[0]-48)*10+((int)s[1]-48);
    float b=((int)s[3]-48)*10+((int)s[4]-48);

    float y=(b*90)/15;
    float x= a*30+(y*30)/360;
   // if(360-y >y) y=360-y;
    //if(360-x < x) x=360-x;
    if(a==12) x=0;
    cout<<x<<" "<<y<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <utility>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>

using namespace std;

#define REP(i,n) for(int i=0; i<(n); ++i)
#define SZ(c) (c).size()
#define FOREACH(it,c) for(typeof((c).begin()) it=(c).begin();it!=(c).end();++it)

int main(void) {
    int h, m;
    scanf("%d:%d", &h, &m);
    double tm = h * 60 + m;
    double gh = (tm * 360) / 720;
    if (gh == 360) gh = 0.0;
    printf("%f %f\n", gh, ((360.0*m)/60.0));
}


#include<stdio.h>
main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int x,y;
scanf("%d:%d",&x,&y);
double s,c;
s=(30.0*x)+(double(y)/2.0);
c=y*6;
if(s==360.0)s=0.0;
printf("%lf %lf\n",s,c);
return 0;
}


#include<iostream>
#include <string>
#include <cstdlib>

using namespace std;

int main()
{
    string a;
    int h, m;
    double hour;
    cin >> a;
    string fh = a.substr(0,2);
    string fm = a.substr(3,2);
    h = atoi(fh.c_str());
    m = atoi(fm.c_str());

    if(h==12 && m==0) {cout << "0 0" << endl; return 0;}
    if(h>23) h = h-12;
    hour = h*30 + double(m/2.);
    cout << hour << " " << m*6 << endl;

    //system("pause");
    return 0;

}


/*mjytxdy!*/
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fir first
#define sec second
#define all(x) x.begin(),x.end()
#define size(x) ((int)x.size())
#define pii pair<int,int>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pll pair<ll,ll>
#define inl inline
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
#define trv(i,u) for(int i=head[u];i;i=e[i].next)
#define lb(x) ((x)&(-(x)))
#define lson root<<1
#define rson root<<1|1
#define debug(x) cout<<#x":"<<x<<'\n'
#define myput puts("QaQ")
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
typedef long long ll;
template<class T>inl bool ylmin(T &a,T b){return a<b?0:(a=b,1);}
template<class T>inl bool ylmax(T &a,T b){return a>b?0:(a=b,1);}
template<class T>inl T abs(T x){return x<0?-x:x;}
inl char read(){
	static const int IO_LEN=1024*1024;
	static char buf[IO_LEN],*ioh,*iot;
	if(ioh==iot){
		iot=(ioh=buf)+fread(buf,1,IO_LEN,stdin);
		if(ioh==iot) return -1;
	}
	return *ioh++;
}
template<class T>inl void read(T &x){
	static int iosig;static char ioc;
	for(iosig=0,ioc=read();!isdigit(ioc);ioc=read()) if(ioc=='-') iosig=1;
	for(x=0;isdigit(ioc);ioc=read())x=(x<<1)+(x<<3)+(ioc^'0');
	if(iosig) x=-x;
}
const int MAXN = 2e5+10;
const int block = sqrt(2e5);
const int inf = 1e9;
const int size = 8e5 + 10 ;
int n,q,l,r,sum[MAXN][26];
char s[MAXN];
vector<int> d[MAXN];
struct Sam{
	int Nodecnt=1,last=1;
	int link[size],len[size],next[size][26],pos[size],flag[size];
	inl void insert(int c,int po){
		int p=last,cur=++Nodecnt;
		pos[cur]=po,len[cur]=len[p]+1,flag[cur]=1;
		for(;p && !next[p][c];p=link[p]) next[p][c]=cur;
		if(!p) link[cur]=1;
		else {
			int q=next[p][c];
			if(len[q]==len[p]+1) link[cur]=q;
			else{
				int clone=++Nodecnt;
				len[clone]=len[q]+1;
				link[clone]=link[q];
				pos[clone]=pos[q];
				rep(i,0,25) next[clone][i]=next[q][i];
				for(;p && next[p][c]==q;p=link[p]) next[p][c]=clone;
				link[cur]=q,link[p]=q;
			}
		}
		last=cur;
	}
};
struct SA{
	Sam sam;
	int sa[size],rank[size],height[size],st[19][size],lg2[size],dfs_time;
	int next[size][26];
	inl void build(){
		rep(i,2,sam.Nodecnt) next[sam.link[i]][s[sam.pos[i]+sam.len[sam.link[i]]]]=i;
	}
	inl void dfs(int u){
		if(sam.flag[u]) sa[rank[sam.pos[u]]=++dfs_time]=sam.pos[u];
		rep(i,0,25) if(next[u][i]) dfs(next[u][i]);
	}
	inl void init(){
		int len=0;
		rep(i,1,n) {
			len=max(0,len-1);
			while(s[i+len]==s[sa[rank[i]-1]+len]) len++;
			st[0][rank[i]]=height[rank[i]]=len;
		}
		rep(i,2,n) lg2[i]=lg2[i>>1]+1;
		rep(i,1,17) rep(j,1,n-(1<<i)+1) st[i][j]=min(st[i-1][j],st[i-1][j+(1<<i-1)]);
	}
	inl int lcp(int l,int r){
		if(l==r) return n-l+1;
		if((l=rank[l])>(r=rank[r])) swap(l,r);
		int k=lg2[r-l]; l++;
		return min(st[k][l],st[k][r-(1<<k)+1]);
	}
}pre,sub;
inl bool check1(int l,int r){
	if(!size(d[2])){
		rep(i,2,n) if(d[i].empty())
			for(int j=i;j<=n;j+=i) d[j].pb(i);
	}
	int len=r-l+1;
	for(auto g:d[len]){
		int tmp=len/g;
		if(pre.lcp(l,l+tmp)>=len-tmp) return true;
	}
	return false;
}
template<size_t size>struct RMQ{
	int st[18][size],lg2[size];
	RMQ(){
		memset(st,0x3f,sizeof(st));
		rep(i,2,n) lg2[i]=lg2[i>>1]+1;
	}
	inl void update(int l,int r,int c){
		if(l>r) return ;
		int k=lg2[r-l+1];
		ylmin(st[k][l],c),ylmin(st[k][r-(1<<k)+1],c);
	}
	inl void init(function<int(int,int)> add,function<int(int,int)> get){
		per(i,17,1)	rep(j,1,n-(1<<i)+1)
			ylmin(st[i-1][j],st[i][j]),ylmin(st[i-1][j+(1<<i-1)],st[i][j]);
		rep(i,1,n) st[0][i]=add(i,st[0][i]);
		rep(i,1,17) rep(j,1,n-(1<<i)+1) st[i][j]=get(st[i-1][j],st[i-1][j+(1<<i-1)]);
	}
	inl int query(int l,int r){
		int k=lg2[r-l+1];
		return min(st[k][l],st[k][r-(1<<k)+1]);
	}
};
RMQ<200005> lrmq,rrmq;
inl build(){
	rep(i,1,n){
		for(int j=i;j+i<=n;j+=i){
			int p=sub.lcp(j,j+i),q=(j+i+1<=n?pre.lcp(j+1,j+i+1):0);
			ylmin(p,i),ylmin(q,i);
			p=j-p+1,q=j+i+q;
			lrmq.update(p,q-2*i+1,i*2);
			rrmq.update(p+2*i-1,q,i*2);
		}
	}
	lrmq.init([](int a,int b){return a+b-1;},[](int a,int b){return min(a,b);});
	rrmq.init([](int a,int b){return a-b+1;},[](int a,int b){return max(a,b);});
}
inl bool check2(int l,int r){
	if(lrmq.st[0][l]<=r || rrmq.st[0][r]>=l) return true;
	int len=min(block,r-l);
	rep(i,1,len) if(pre.lcp(l,r-i+1)>=i) return i*2<=r-l+1;
	if(len!=block) return false;
	int t=n/block+1,lpos=max(1,pre.rank[l]-t),rpos=min(n,pre.rank[l]+t),res=inf;
	rep(i,lpos,rpos)
		if(pre.sa[i]>=l && pre.sa[i]<=r && pre.lcp(l,pre.sa[i])>=r-pre.sa[i]) ylmin(res,r-pre.sa[i]+1);
	return res*2<=r-l+1;
}
inl bool check3(int l,int r){
	if(sum[r][s[l]]-sum[l-1][s[l]]>1 || sum[r][s[r]]-sum[l-1][s[r]]>1) return true;
	return lrmq.query(l,r)<=r;
}
inl bool check0(int l,int r){
	bool flag=0;
	rep(i,0,25) flag|=(sum[r][i]-sum[l-1][i]>1);
	return !flag;
}
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d%s%d",&n,s+1,&q);
	rep(i,1,n) s[i]-='a';
	rep(i,1,n) rep(j,0,25) sum[i][j]=sum[i-1][j]+(s[i]==j);
	per(i,n,1) pre.sam.insert(s[i],i);
	rep(i,1,n) sub.sam.insert(s[i],i);
	pre.build(),pre.dfs(1),pre.init();
	sub.build(),sub.dfs(1),sub.init();
	build();
	while(q--){
		read(l),read(r);
		if(check0(l,r)) puts("-1");
		else if(check1(l,r)) puts("1");
		else if(check2(l,r)) puts("2");
		else if(check3(l,r)) puts("3");
		else puts("4");
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define all(a) (a).begin(), (a).end()
#define pii pair <int, int>

const int maxn = 2e5 + 10;
const int logn = 19;
const int alf = 26;

int pw2[logn];
int lg2[maxn];

void make_sparse() {
    pw2[0] = 1;
    for (int i = 1; i < logn; i++) {
        pw2[i] = 2 * pw2[i - 1];
    }
    lg2[0] = -1;
    for (int i = 1; i < maxn; i++) {
        lg2[i] = lg2[i / 2] + 1;
    }
}

struct sparse_max {
    vector<vector<int>> table;
    int n;
    sparse_max() {}
    sparse_max(vector<int> &v) {
        n = v.size();

        int logn1 = 1;
        while (pw2[logn1] <= n) logn1++;
        table.resize(n, vector<int> (logn1));
        for (int i = 0; i < n; i++) {
            table[i][0] = v[i];
        }
        for (int c = 1; c < logn1; c++) {
            for (int i = 0; i < n; i++) {
                if (i + pw2[c - 1] < n) {
                    table[i][c] = max(table[i][c - 1], table[i + pw2[c - 1]][c - 1]);
                } else {
                    table[i][c] = table[i][c - 1];
                }
            }
        }
    }
    int get(int l, int r) {
        // полуинтервал
        if (r <= l) return 0;
        return max(table[l][lg2[r - l]], table[r - pw2[lg2[r - l]]][lg2[r - l]]);
    }
};

struct sparse_min {
    vector<vector<int>> table;
    int n;
    sparse_min() {}
    sparse_min(vector<int> &v) {
        n = v.size();
        int logn1 = 1;
        while (pw2[logn1] <= n) logn1++;
        table.resize(n, vector<int> (logn1));
        for (int i = 0; i < n; i++) {
            table[i][0] = v[i];
        }
        for (int c = 1; c < logn1; c++) {
            for (int i = 0; i < n; i++) {
                if (i + pw2[c - 1] < n) {
                    table[i][c] = min(table[i][c - 1], table[i + pw2[c - 1]][c - 1]);
                } else {
                    table[i][c] = table[i][c - 1];
                }
            }
        }
    }
    int get(int l, int r) {
        // полуинтервал
        if (r <= l) return maxn;
        return min(table[l][lg2[r - l]], table[r - pw2[lg2[r - l]]][lg2[r - l]]);
    }
};

struct cnt_tree {
    vector<vector<int>> tree;
    int n;
    cnt_tree() {}

    void make_cnt(vector<int> &v, char h) {
        v.resize(alf);
        v[h - 'a'] = 1;
    }

    void sum_cnt(vector<int> &v, vector<int> &l, vector<int> &r) {
        for (int i = 0; i < alf; i++) {
            v[i] = l[i] + r[i];
        }
    }

    void build(const string &s, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            make_cnt(tree[v], s[tl]);
            return;
        }
        int tm = (tl + tr) / 2;
        build(s, 2 * v + 1, tl, tm);
        build(s, 2 * v + 2, tm, tr);
        tree[v].resize(alf);
        sum_cnt(tree[v], tree[2 * v + 1], tree[2 * v + 2]);
    }

    cnt_tree(const string &s) {
        n = s.size();
        tree.resize(4 * n);
        build(s, 0, 0, n);
    }

    void get(vector<int> &ans, int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return;
        if (tl >= l && tr <= r) {
            sum_cnt(ans, ans, tree[v]);
            return;
        }
        int tm = (tl + tr) / 2;
        get(ans, 2 * v + 1, tl, tm, l, r);
        get(ans, 2 * v + 2, tm, tr, l, r);
    }

    vector<int> get(int l, int r) {
        vector<int> ans(alf);
        get(ans, 0, 0, n, l, r);
        return ans;
    }
};

struct min_tree {
    vector<int> tree;
    int n;
    min_tree() {};
    void build(vector<int> &a, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            tree[v] = a[tl];
            return;
        }
        int tm = (tl + tr) / 2;
        build(a, 2 * v + 1, tl, tm);
        build(a, 2 * v + 2, tm, tr);
        tree[v] = min(tree[2 * v + 1], tree[2 * v + 2]);
    }
    min_tree(vector<int> & a) {
        n = a.size();
        tree.resize(4 * n);
        build(a, 0, 0, n);
    }

    int get(int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return maxn;
        if (tl >= l && tr <= r) return tree[v];
        int tm = (tl + tr) / 2;
        return min(get(2 * v + 1, tl, tm, l, r), get(2 * v + 2, tm, tr, l, r));
    }

    int get(int l, int r) {
        return get(0, 0, n, l, r);
    }
};

struct max_tree {
    vector<int> tree;
    int n;
    max_tree() {};
    void build(vector<int> &a, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            tree[v] = a[tl];
            return;
        }
        int tm = (tl + tr) / 2;
        build(a, 2 * v + 1, tl, tm);
        build(a, 2 * v + 2, tm, tr);
        tree[v] = max(tree[2 * v + 1], tree[2 * v + 2]);
    }
    max_tree(vector<int> & a) {
        n = a.size();
        tree.resize(4 * n);
        build(a, 0, 0, n);
    }

    int get(int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return 0;
        if (tl >= l && tr <= r) return tree[v];
        int tm = (tl + tr) / 2;
        return max(get(2 * v + 1, tl, tm, l, r), get(2 * v + 2, tm, tr, l, r));
    }

    int get(int l, int r) {
        return get(0, 0, n, l, r);
    }
};

vector<int> prefix_function(string s) {
    int n = (int) s.length();
    vector<int> pi(n);
    for (int i = 1; i < n; ++i) {
        int j = pi[i - 1];
        while (j > 0 && s[i] != s[j])
            j = pi[j - 1];
        if (s[i] == s[j])  ++j;
        pi[i] = j;
    }
    return pi;
}

vector<int> suff(string &s) {
    s += '$';
    int n = s.size();
    vector<int> cnt(27);
    for (int i = 0; i < n - 1; i++)
        cnt[s[i] - 'a']++;
    vector<int> pos(27);
    pos[0] = 1;
    for (int i = 1; i < 27; i++)
        pos[i] = pos[i - 1] + cnt[i - 1];
    vector<int> a(n);
    for (int i = 0; i < n - 1; i++)
        a[pos[s[i] - 'a']++] = i;
    a[0] = n - 1;
    vector<int> c(n);
    int cc = 0;
    for (int i = 0; i < n - 1; i++) {
        c[a[i]] = cc;
        if (s[a[i]] != s[a[i + 1]]) cc++;
    }
    c[a[n - 1]] = cc;
    cnt.resize(n);
    pos.resize(n);
    for (int l = 1; l < n; l *= 2) {
        cnt.assign(n, 0);
        for (int i = 0; i < n; i++)
            cnt[c[i]]++;
        pos[0] = 0;
        for (int i = 1; i < n; i++)
            pos[i] = pos[i - 1] + cnt[i - 1];
        vector<int> na(n);
        for (int i = 0; i < n; i++) {
            int ind = (a[i] - l + n) % n;
            na[pos[c[ind]]++] = ind;
        }
        a = na;

        vector<int> nc(n);
        cc = 0;
        for (int i = 0; i < n - 1; i++) {
            nc[a[i]] = cc;
            if (c[a[i]] != c[a[i + 1]] || c[(a[i] + l) % n]!= c[(a[i + 1] + l) % n]) cc++;
        }
        nc[a[n - 1]] = cc;
        c = nc;
    }
    // a.erase(a.begin());
    return a;
}

void relax(int &a, int b) {
    a = min(a, b);
}

void relax_mx(int &a, int b) {
    a = max(a, b);
}

vector<int> pos_create;

bool cmp(int a, int b) {
    return pos_create[a] < pos_create[b];
}

struct all_about_one_string {
    int n;
    string s;
    min_tree easy_tree;
    vector<int> suf;
    vector<int> lcp;
    vector<int> pos;
    sparse_min sparse_lcp;
    vector<int> for_st;

    int get_lcp(int a, int b) {
        a = pos[a];
        b = pos[b];
        if (a > b) swap(a, b);
        return sparse_lcp.get(a + 1, b + 1);
    }

    vector<vector<int>> mst;
    vector<vector<int>> left_right;
    vector<vector<int>> right_left;

    vector<vector<int>> le_ri_2;
    vector<vector<int>> ri_le_2;

    vector<max_tree> spmx;
    vector<min_tree> spmn;
    void build(int v, int tl, int tr) {
        if (tl + 1 == tr) {
            mst[v] = {tl};
            return;
        }
        int tm = (tl + tr) / 2;
        build(2 * v + 1, tl, tm);
        build(2 * v + 2, tm, tr);
        mst[v].resize(tr - tl);
        merge(all(mst[2 * v + 1]), all(mst[2 * v + 2]), mst[v].begin(), cmp);
        spmx[v] = max_tree(mst[v]);
        spmn[v] = min_tree(mst[v]);

        vector<pii> stack = {{0, -1}};
        left_right[v].resize(tr - tl);
        left_right[v][0] = -1;
        for (int i = 1; i < tr - tl; i++) {
            int lp = get_lcp(mst[v][i - 1], mst[v][i]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            left_right[v][i] = max(left_right[v][stack.back().first], spmx[v].get(stack.back().first, i) + lp);
            stack.push_back({i, lp});
        }

        // заполни, можно без бинпоисков
        stack = {{tr - tl - 1, -1}};
        right_left[v].resize(tr - tl);
        right_left[v][tr - tl - 1] = -1;
        for (int i = tr - tl - 2; i >= 0; i--) {
            int lp = get_lcp(mst[v][i], mst[v][i + 1]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            right_left[v][i] = max(right_left[v][stack.back().first], spmx[v].get(i + 1, stack.back().first + 1) + lp);
            stack.push_back({i, lp});
        }

        // аналогично

        stack = {{0, -maxn}};
        le_ri_2[v].resize(tr - tl);
        le_ri_2[v][0] = -maxn;
        for (int i = 1; i < tr - tl; i++) {
            int lp = get_lcp(mst[v][i - 1], mst[v][i]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            le_ri_2[v][i] = max(le_ri_2[v][stack.back().first], - spmn[v].get(stack.back().first, i) + lp);
            stack.push_back({i, lp});
        }

        // заполни, можно без бинпоисков
        stack = {{tr - tl - 1, -maxn}};
        ri_le_2[v].resize(tr - tl);
        ri_le_2[v][tr - tl - 1] = -maxn;
        for (int i = tr - tl - 2; i >= 0; i--) {
            int lp = get_lcp(mst[v][i], mst[v][i + 1]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            ri_le_2[v][i] = max(ri_le_2[v][stack.back().first], - spmn[v].get(i + 1, stack.back().first + 1) + lp);
            stack.push_back({i, lp});
        }

    }

    void make_mst() {
        mst.resize(4 * n);
        spmx.resize(4 * n);
        spmn.resize(4 * n);
        left_right.resize(4 * n);
        right_left.resize(4 * n);
        le_ri_2.resize(4 * n);
        ri_le_2.resize(4 * n);
        build(0, 0, n);
    }

    int get_inside(int v, int tl, int tr, int l, int r, bool pre) {
        int lll = -1;
        int rrr = tr - tl;
        while (lll + 1 < rrr) {
            int m = (lll + rrr) / 2;
            // cout << "m = " << m << endl;
            if (cmp(l - 1, mst[v][m])) {
                rrr = m;
            } else {
                lll = m;
            }
            // cout << "h" << endl;
        }

        //int p1 = upper_bound(all(mst[v]), l - 1, cmp) - mst[v].begin();
        int p1 = rrr;

        int eqr;
        if (p1 == tr - tl) {
            eqr = 0;
        } else {
            eqr = get_lcp(l - 1, mst[v][p1]);
        }

        int bl = p1;
        int br = tr - tl;
        while (bl + 1 < br) {
            int bm = (bl + br) / 2;
            if (get_lcp(mst[v][bm], l - 1) >= eqr) {
                bl = bm;
            } else {
                br = bm;
            }
        }

        int eql;
        if (p1 == 0) {
            eql = 0;
        } else {
            eql = get_lcp(l - 1, mst[v][p1 - 1]);
        }
        int bl1 = p1;
        int br1 = -1;
        while (br1 + 1 < bl1) {
            int bm = (bl1 + br1 + 1) / 2;
            if (get_lcp(mst[v][bm], l - 1) >= eql) {
                bl1 = bm;
            } else {
                br1 = bm;
            }
        }
        //cout << "h " << endl;
        // cout << bl1 << ' ' << p1 << endl;
        int ans = -maxn;
        if (pre == 1) {
            relax_mx(ans, spmx[v].get(bl1, p1) + eql);
            // cout << "ans = " << ans << endl;
            relax_mx(ans, spmx[v].get(p1, br) + eqr);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            if (bl1 >= 0) relax_mx(ans, left_right[v][bl1]);
            // cout << "ans = " << ans << endl;
            if (br != tr - tl) relax_mx(ans, right_left[v][bl]);
            // cout << "h " << endl;
            // cout << "ans for " << l - 1 << ' ' << tl << ' ' << tr << " = " << ans << endl;
            if (ans >= r) return 1;
            return 0;
        } else {
            relax_mx(ans, -spmn[v].get(bl1, p1) + eql);
            // cout << "ans = " << ans << endl;
            relax_mx(ans, -spmn[v].get(p1, br) + eqr);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            if (bl1 >= 0) relax_mx(ans, le_ri_2[v][bl1]);
            // cout << "ans = " << ans << endl;
            if (br != tr - tl) relax_mx(ans, ri_le_2[v][bl]);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            // cout << "for " << l - 1 << ' ' << tl << ' ' << tr << " ans = " << ans << '\n';
            if (ans + l > 0) return 1;
            return 0;
        }

    }

    int get_prefix(int v, int tl, int tr, int l, int r) {
        // cout << "h = " << tl << ' ' << tr << ' ' << l << endl;
        if (tl >= r || tr <= l) return maxn;
        if (tl + 1 == tr) {
            // cout << "get_lcp(" << l << ' ' << tl << ") = " << get_lcp(l, tl) << '\n';
            if (get_lcp(l - 1, tl) + tl >= r) return tl;
            return maxn;
        }
        int tm = (tl + tr) / 2;
        if (tl >= l && tr <= r) {
            // переделать
            if (!get_inside(v, tl, tr, l, r, 1)) {
                // cout << "get1" << endl;
                return maxn;
            } // cout << "get2" << endl;
            int g1 = get_prefix(2 * v + 1, tl, tm, l, r);
            if (g1 != maxn) return g1;
            return get_prefix(2 * v + 2, tm, tr, l, r);
        }
        int g1 = get_prefix(2 * v + 1, tl, tm, l, r);
        if (g1 != maxn) return g1;
        return get_prefix(2 * v + 2, tm, tr, l, r);
    }

    int get_repeat(int v, int tl, int tr, int l) {
        // cout << "h = " << tl << ' ' << tr << endl;
        if (tr <= l) return maxn;
        if (tl + 1 == tr) {
            // cout << "get_lcp(" << l << ' ' << tl << ") = " << get_lcp(l, tl) << '\n';
            if (get_lcp(l - 1, tl) + l - 1 >= tl) return tl;
            return maxn;
        }
        int tm = (tl + tr) / 2;
        if (tl >= l) {
            // переделать
            //cout << "get_inside " << v << ' ' << tl << ' ' << tr << ' ' << l << endl;
            if (!get_inside(v, tl, tr, l, 0, 0)) {
                // cout << "geted1" << endl;
                return maxn;
            } // cout << "geted2" << endl;
            int g1 = get_repeat(2 * v + 1, tl, tm, l);
            if (g1 != maxn) return g1;
            return get_repeat(2 * v + 2, tm, tr, l);
        }
        int g1 = get_repeat(2 * v + 1, tl, tm, l);
        if (g1 != maxn) return g1;
        return get_repeat(2 * v + 2, tm, tr, l);
    }

    int get_prefix(int l, int r) {
        int g = get_prefix(0, 0, n, l + 1, r);
        // cout << "g = " << g << '\n';
        if (g == maxn) return 0;
        // cout << "g = " << g << '\n';
        return r - g;
    }

    int get_start(int l, int r) {
        if (for_st[l] <= r) return 2;
        return 5;
    }

    void make_center() {
        for_st.resize(n, maxn);
        // cout << "here = make_center" << endl;
        for (int l = 0; l < n; l++) {
            // cout << l << endl;
            // cout << "l = " << l << endl;
            for_st[l] = 2 * get_repeat(0, 0, n, l + 1) - l;
        }

        easy_tree = min_tree(for_st);
    }

    int get_center(int l, int r) {
        int r1 = easy_tree.get(l, r);
        if (r1 <= r) return 3;
        return 5;
    }

    all_about_one_string() {}
    all_about_one_string(string s_) {
        s = s_;
        suf = suff(s);
        n = s.size();

        pos.resize(n);
        for (int i = 0; i < n; i++) {
            pos[suf[i]] = i;
        }
        pos_create = pos;

        lcp.resize(n);
        int last = 0;
        for (int i = 0; i < n - 1; i++) {
            int j = pos[i];
            lcp[j] = last;
            for (int p = last; ; p++) {
                if (s[i + p] == s[suf[j - 1] + p]) {
                    lcp[j]++;
                } else {
                    break;
                }
            }
            last = max(0, lcp[j] - 1);
        }

        sparse_lcp = sparse_min(lcp);
        // cout << "here" << endl;
        // cout << "make mst" << endl;
        make_mst();
        // cout << "make center" << endl;
        // cout << "here" << endl;
        make_center();
        // cout << "finished" << endl;
        // cout << get_lcp(0, 3) << '\n';
    }

    int get(int l, int r) {
        int best = 5;
        int pr = get_prefix(l, r);
        // cout << "get_prefix = " << pr << '\n';
        if (pr != 0) {
            int k = r - l - pr;
            if ((r - l) % k == 0) {
                relax(best, 1);
            } else {
                relax(best, 2);
            }
        }
        relax(best, get_start(l, r));
        // pr = get_start(l, r);
        // // cout << "get_start = " << pr << '\n';
        // if (pr <= r) relax(best, 2);

        relax(best, get_center(l, r));
        // cout << "get_center = " << pr << '\n';
        return best;
    }
};

string s;
string rev_s;
int n;

cnt_tree cnt;
all_about_one_string al1;
all_about_one_string al2;

void make() {
    make_sparse();
    cnt = cnt_tree(s);
    al1 = all_about_one_string(s);
    al2 = all_about_one_string(rev_s);
}

int full_get(int l, int r) {
    vector<int> cnt1 = cnt.get(l, r);
    int best = 5;
    for (int i = 0; i < alf; i++) {
        if (cnt1[i] > 1) relax(best, 4);
    }
    if (best == 5) return -1;
    // cout << "cnt_ans_1 = " << best << '\n';
    if (cnt1[s[l] - 'a'] > 1) relax(best, 3);
    // cout << "cnt_ans_2 = " << best << '\n';
    if (cnt1[s[r - 1] - 'a'] > 1) relax(best, 3);
    // cout << "cnt_ans_3 = " << best << '\n';
    relax(best, al1.get(l, r));
    // cout << "al1_ans = " << best << '\n';
    relax(best, al2.get(n - r, n - l));
    return best - 6 * (best == 5);
}

void input() {
    cin >> n;
    cin >> s;
    for (int i = n - 1; i >= 0; i--) {
        rev_s += s[i];
    }
}

void solve() {
    int q;
    cin >> q;
    int l, r;
    for (int i = 0; i < q; i++) {
        cin >> l >> r;
        l--;
        cout << full_get(l, r) << '\n';
    }
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    input();
    // cout << "h1" << endl;
    make();
    // cout << "h2" << endl;
    solve();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define all(a) (a).begin(), (a).end()
#define pii pair <int, int>

const int maxn = 2e5 + 10;
const int logn = 19;
const int alf = 26;

int pw2[logn];
int lg2[maxn];

void make_sparse() {
    pw2[0] = 1;
    for (int i = 1; i < logn; i++) {
        pw2[i] = 2 * pw2[i - 1];
    }
    lg2[0] = -1;
    for (int i = 1; i < maxn; i++) {
        lg2[i] = lg2[i / 2] + 1;
    }
}

struct sparse_max {
    vector<vector<int>> table;
    int n;
    sparse_max() {}
    sparse_max(vector<int> &v) {
        n = v.size();

        int logn1 = 1;
        while (pw2[logn1] <= n) logn1++;
        table.resize(n, vector<int> (logn1));
        for (int i = 0; i < n; i++) {
            table[i][0] = v[i];
        }
        for (int c = 1; c < logn1; c++) {
            for (int i = 0; i < n; i++) {
                if (i + pw2[c - 1] < n) {
                    table[i][c] = max(table[i][c - 1], table[i + pw2[c - 1]][c - 1]);
                } else {
                    table[i][c] = table[i][c - 1];
                }
            }
        }
    }
    int get(int l, int r) {
        // полуинтервал
        if (r <= l) return 0;
        return max(table[l][lg2[r - l]], table[r - pw2[lg2[r - l]]][lg2[r - l]]);
    }
};

struct sparse_min {
    vector<vector<int>> table;
    int n;
    sparse_min() {}
    sparse_min(vector<int> &v) {
        n = v.size();
        int logn1 = 1;
        while (pw2[logn1] <= n) logn1++;
        table.resize(n, vector<int> (logn1));
        for (int i = 0; i < n; i++) {
            table[i][0] = v[i];
        }
        for (int c = 1; c < logn1; c++) {
            for (int i = 0; i < n; i++) {
                if (i + pw2[c - 1] < n) {
                    table[i][c] = min(table[i][c - 1], table[i + pw2[c - 1]][c - 1]);
                } else {
                    table[i][c] = table[i][c - 1];
                }
            }
        }
    }
    int get(int l, int r) {
        // полуинтервал
        if (r <= l) return maxn;
        return min(table[l][lg2[r - l]], table[r - pw2[lg2[r - l]]][lg2[r - l]]);
    }
};

struct cnt_tree {
    vector<vector<int>> tree;
    int n;
    cnt_tree() {}

    void make_cnt(vector<int> &v, char h) {
        v.resize(alf);
        v[h - 'a'] = 1;
    }

    void sum_cnt(vector<int> &v, vector<int> &l, vector<int> &r) {
        for (int i = 0; i < alf; i++) {
            v[i] = l[i] + r[i];
        }
    }

    void build(const string &s, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            make_cnt(tree[v], s[tl]);
            return;
        }
        int tm = (tl + tr) / 2;
        build(s, 2 * v + 1, tl, tm);
        build(s, 2 * v + 2, tm, tr);
        tree[v].resize(alf);
        sum_cnt(tree[v], tree[2 * v + 1], tree[2 * v + 2]);
    }

    cnt_tree(const string &s) {
        n = s.size();
        tree.resize(4 * n);
        build(s, 0, 0, n);
    }

    void get(vector<int> &ans, int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return;
        if (tl >= l && tr <= r) {
            sum_cnt(ans, ans, tree[v]);
            return;
        }
        int tm = (tl + tr) / 2;
        get(ans, 2 * v + 1, tl, tm, l, r);
        get(ans, 2 * v + 2, tm, tr, l, r);
    }

    vector<int> get(int l, int r) {
        vector<int> ans(alf);
        get(ans, 0, 0, n, l, r);
        return ans;
    }
};

struct min_tree {
    vector<int> tree;
    int n;
    min_tree() {}
    void build(vector<int> &a, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            tree[v] = a[tl];
            return;
        }
        int tm = (tl + tr) / 2;
        build(a, 2 * v + 1, tl, tm);
        build(a, 2 * v + 2, tm, tr);
        tree[v] = min(tree[2 * v + 1], tree[2 * v + 2]);
    }
    min_tree(vector<int> & a) {
        n = a.size();
        tree.resize(4 * n);
        build(a, 0, 0, n);
    }

    int get(int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return maxn;
        if (tl >= l && tr <= r) return tree[v];
        int tm = (tl + tr) / 2;
        return min(get(2 * v + 1, tl, tm, l, r), get(2 * v + 2, tm, tr, l, r));
    }

    int get(int l, int r) {
        return get(0, 0, n, l, r);
    }
};

struct max_tree {
    vector<int> tree;
    int n;
    max_tree() {}
    void build(vector<int> &a, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            tree[v] = a[tl];
            return;
        }
        int tm = (tl + tr) / 2;
        build(a, 2 * v + 1, tl, tm);
        build(a, 2 * v + 2, tm, tr);
        tree[v] = max(tree[2 * v + 1], tree[2 * v + 2]);
    }
    max_tree(vector<int> & a) {
        n = a.size();
        tree.resize(4 * n);
        build(a, 0, 0, n);
    }

    int get(int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return 0;
        if (tl >= l && tr <= r) return tree[v];
        int tm = (tl + tr) / 2;
        return max(get(2 * v + 1, tl, tm, l, r), get(2 * v + 2, tm, tr, l, r));
    }

    int get(int l, int r) {
        return get(0, 0, n, l, r);
    }
};

vector<int> suff(string &s) {
    s += '$';
    int n = s.size();
    vector<int> cnt(27);
    for (int i = 0; i < n - 1; i++)
        cnt[s[i] - 'a']++;
    vector<int> pos(27);
    pos[0] = 1;
    for (int i = 1; i < 27; i++)
        pos[i] = pos[i - 1] + cnt[i - 1];
    vector<int> a(n);
    for (int i = 0; i < n - 1; i++)
        a[pos[s[i] - 'a']++] = i;
    a[0] = n - 1;
    vector<int> c(n);
    int cc = 0;
    for (int i = 0; i < n - 1; i++) {
        c[a[i]] = cc;
        if (s[a[i]] != s[a[i + 1]]) cc++;
    }
    c[a[n - 1]] = cc;
    cnt.resize(n);
    pos.resize(n);
    for (int l = 1; l < n; l *= 2) {
        cnt.assign(n, 0);
        for (int i = 0; i < n; i++)
            cnt[c[i]]++;
        pos[0] = 0;
        for (int i = 1; i < n; i++)
            pos[i] = pos[i - 1] + cnt[i - 1];
        vector<int> na(n);
        for (int i = 0; i < n; i++) {
            int ind = (a[i] - l + n) % n;
            na[pos[c[ind]]++] = ind;
        }
        a = na;

        vector<int> nc(n);
        cc = 0;
        for (int i = 0; i < n - 1; i++) {
            nc[a[i]] = cc;
            if (c[a[i]] != c[a[i + 1]] || c[(a[i] + l) % n]!= c[(a[i + 1] + l) % n]) cc++;
        }
        nc[a[n - 1]] = cc;
        c = nc;
    }
    // a.erase(a.begin());
    return a;
}

void relax(int &a, int b) {
    a = min(a, b);
}

void relax_mx(int &a, int b) {
    a = max(a, b);
}

vector<int> pos_create;

bool cmp(int a, int b) {
    return pos_create[a] < pos_create[b];
}

struct all_about_one_string {
    int n;
    string s;
    min_tree easy_tree;
    vector<int> suf;
    vector<int> lcp;
    vector<int> pos;
    sparse_min sparse_lcp;
    vector<int> for_st;

    int get_lcp(int a, int b) {
        a = pos[a];
        b = pos[b];
        if (a > b) swap(a, b);
        return sparse_lcp.get(a + 1, b + 1);
    }

    vector<vector<int>> mst;
    vector<vector<int>> left_right;
    vector<vector<int>> right_left;

    vector<vector<int>> le_ri_2;
    vector<vector<int>> ri_le_2;

    vector<max_tree> spmx;
    vector<min_tree> spmn;
    void build(int v, int tl, int tr) {
        if (tl + 1 == tr) {
            mst[v] = {tl};
            return;
        }
        int tm = (tl + tr) / 2;
        build(2 * v + 1, tl, tm);
        build(2 * v + 2, tm, tr);
        mst[v].resize(tr - tl);
        merge(all(mst[2 * v + 1]), all(mst[2 * v + 2]), mst[v].begin(), cmp);
        spmx[v] = max_tree(mst[v]);
        spmn[v] = min_tree(mst[v]);

        vector<pii> stack = {{0, -1}};
        left_right[v].resize(tr - tl);
        left_right[v][0] = -1;
        for (int i = 1; i < tr - tl; i++) {
            int lp = get_lcp(mst[v][i - 1], mst[v][i]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            left_right[v][i] = max(left_right[v][stack.back().first], spmx[v].get(stack.back().first, i) + lp);
            stack.push_back({i, lp});
        }

        // заполни, можно без бинпоисков
        stack = {{tr - tl - 1, -1}};
        right_left[v].resize(tr - tl);
        right_left[v][tr - tl - 1] = -1;
        for (int i = tr - tl - 2; i >= 0; i--) {
            int lp = get_lcp(mst[v][i], mst[v][i + 1]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            right_left[v][i] = max(right_left[v][stack.back().first], spmx[v].get(i + 1, stack.back().first + 1) + lp);
            stack.push_back({i, lp});
        }

        // аналогично
        stack = {{0, -maxn}};
        le_ri_2[v].resize(tr - tl);
        le_ri_2[v][0] = -maxn;
        for (int i = 1; i < tr - tl; i++) {
            int lp = get_lcp(mst[v][i - 1], mst[v][i]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            le_ri_2[v][i] = max(le_ri_2[v][stack.back().first], - spmn[v].get(stack.back().first, i) + lp);
            stack.push_back({i, lp});
        }

        // заполни, можно без бинпоисков
        stack = {{tr - tl - 1, -maxn}};
        ri_le_2[v].resize(tr - tl);
        ri_le_2[v][tr - tl - 1] = -maxn;
        for (int i = tr - tl - 2; i >= 0; i--) {
            int lp = get_lcp(mst[v][i], mst[v][i + 1]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            ri_le_2[v][i] = max(ri_le_2[v][stack.back().first], - spmn[v].get(i + 1, stack.back().first + 1) + lp);
            stack.push_back({i, lp});
        }
    }

    void make_mst() {
        mst.resize(4 * n);
        spmx.resize(4 * n);
        spmn.resize(4 * n);
        left_right.resize(4 * n);
        right_left.resize(4 * n);
        le_ri_2.resize(4 * n);
        ri_le_2.resize(4 * n);
        build(0, 0, n);
    }

    int get_inside(int v, int tl, int tr, int l, int r, bool pre) {
        int lll = -1;
        int rrr = tr - tl;
        while (lll + 1 < rrr) {
            int m = (lll + rrr) / 2;
            // cout << "m = " << mst[v][m] << '\n';
            // cout << "l - 1 = " << l - 1 << '\n';
            // cout << "m = " << m << endl;
            if (pos[l - 1] < pos[mst[v][m]]) {
                rrr = m;
            } else {
                lll = m;
            }
            // cout << "h" << endl;
        }
        // cout << '\n';

        // int p1 = upper_bound(all(mst[v]), l - 1, cmp) - mst[v].begin();
        int p1 = rrr;

        int eqr;
        if (p1 == tr - tl) {
            eqr = 0;
        } else {
            eqr = get_lcp(l - 1, mst[v][p1]);
        }

        int bl = p1;
        int br = tr - tl;
        while (bl + 1 < br) {
            int bm = (bl + br) / 2;
            if (get_lcp(mst[v][bm], l - 1) >= eqr) {
                bl = bm;
            } else {
                br = bm;
            }
        }

        int eql;
        if (p1 == 0) {
            eql = 0;
        } else {
            eql = get_lcp(l - 1, mst[v][p1 - 1]);
        }
        int bl1 = p1;
        int br1 = -1;
        while (br1 + 1 < bl1) {
            int bm = (bl1 + br1 + 1) / 2;
            if (get_lcp(mst[v][bm], l - 1) >= eql) {
                bl1 = bm;
            } else {
                br1 = bm;
            }
        }
        // cout << "h " << endl;
        // cout << bl1 << ' ' << p1 << endl;
        int ans = -maxn;
        if (pre == 1) {
            relax_mx(ans, spmx[v].get(bl1, p1) + eql);
            // cout << "ans = " << ans << endl;
            relax_mx(ans, spmx[v].get(p1, br) + eqr);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            if (bl1 >= 0) relax_mx(ans, left_right[v][bl1]);
            // cout << "ans = " << ans << endl;
            if (br != tr - tl) relax_mx(ans, right_left[v][bl]);

            if (ans >= r) return 1;
            return 0;
        } else {
            relax_mx(ans, -spmn[v].get(bl1, p1) + eql);
            // cout << "ans = " << ans << endl;
            relax_mx(ans, -spmn[v].get(p1, br) + eqr);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            if (bl1 >= 0) relax_mx(ans, le_ri_2[v][bl1]);
            // cout << "ans = " << ans << endl;
            if (br != tr - tl) relax_mx(ans, ri_le_2[v][bl]);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            // cout << "for " << l - 1 << ' ' << tl << ' ' << tr << " ans = " << ans << '\n';
            if (ans + l > 0) return 1;
            return 0;
        }
    }

    int get_prefix(int v, int tl, int tr, int l, int r) {
        // cout << "h = " << tl << ' ' << tr << ' ' << l << endl;
        if (tl >= r || tr <= l) return maxn;
        if (tl + 1 == tr) {
            // cout << "get_lcp(" << l << ' ' << tl << ") = " << get_lcp(l, tl) << '\n';
            if (get_lcp(l - 1, tl) + tl >= r) return tl;
            return maxn;
        }
        int tm = (tl + tr) / 2;
        if (tl >= l && tr <= r) {
            // переделать
            if (!get_inside(v, tl, tr, l, r, 1)) {
                // cout << "get1" << endl;
                return maxn;
            }
            // cout << "get2" << endl;
            int g1 = get_prefix(2 * v + 1, tl, tm, l, r);
            if (g1 != maxn) return g1;
            return get_prefix(2 * v + 2, tm, tr, l, r);
        }
        int g1 = get_prefix(2 * v + 1, tl, tm, l, r);
        if (g1 != maxn) return g1;
        return get_prefix(2 * v + 2, tm, tr, l, r);
    }

    int get_repeat(int v, int tl, int tr, int l) {
        // cout << "h = " << tl << ' ' << tr << endl;
        if (tr <= l) return maxn;
        if (tl + 1 == tr) {
            // cout << "get_lcp(" << l << ' ' << tl << ") = " << get_lcp(l, tl) << '\n';
            if (get_lcp(l - 1, tl) + l - 1 >= tl) return tl;
            return maxn;
        }
        int tm = (tl + tr) / 2;
        if (tl >= l) {
            // переделать
            // cout << "get_inside " << v << ' ' << tl << ' ' << tr << ' ' << l << endl;
            if (!get_inside(v, tl, tr, l, 0, 0)) {
                // cout << "geted1" << endl;
                return maxn;
            }
            // cout << "geted2" << endl;
            int g1 = get_repeat(2 * v + 1, tl, tm, l);
            if (g1 != maxn) return g1;
            return get_repeat(2 * v + 2, tm, tr, l);
        }
        int g1 = get_repeat(2 * v + 1, tl, tm, l);
        if (g1 != maxn) return g1;
        return get_repeat(2 * v + 2, tm, tr, l);
    }

    int get_prefix(int l, int r) {
        int g = get_prefix(0, 0, n, l + 1, r);
        // cout << "get_prefix = " << g << '\n';
        if (g == maxn) return 0;
        // cout << "g = " << g << '\n';
        return r - g;
    }

    int get_start(int l, int r) {
        if (for_st[l] <= r) return 2;
        return 5;
    }

    void make_center() {
        for_st.resize(n, maxn);
        // cout << "here = make_center" << endl;
        for (int l = 0; l < n; l++) {
            // cout << l << endl;
            // cout << "l = " << l << endl;
            for_st[l] = 2 * get_repeat(0, 0, n, l + 1) - l;
        }

        easy_tree = min_tree(for_st);
    }

    int get_center(int l, int r) {
        int r1 = easy_tree.get(l, r);
        if (r1 <= r) return 3;
        return 5;
    }

    all_about_one_string() {}
    all_about_one_string(string s_) {
        s = s_;
        suf = suff(s);
        n = s.size();

        pos.resize(n);
        for (int i = 0; i < n; i++) {
            pos[suf[i]] = i;
        }
        // for (int i = 0; i < n; i++) {
        //     cout << pos[i] << ' ';
        // } cout << '\n';
        pos_create = pos;

        lcp.resize(n);
        int last = 0;
        for (int i = 0; i < n - 1; i++) {
            int j = pos[i];
            lcp[j] = last;
            for (int p = last; ; p++) {
                if (s[i + p] == s[suf[j - 1] + p]) {
                    lcp[j]++;
                } else {
                    break;
                }
            }
            last = max(0, lcp[j] - 1);
        }

        sparse_lcp = sparse_min(lcp);
        // cout << "here" << endl;
        // cout << "make mst" << endl;
        make_mst();
        // cout << "make center" << endl;
        // cout << "here" << endl;
        make_center();
        // cout << "finished" << endl;
        // cout << get_lcp(0, 3) << '\n';
    }

    int get(int l, int r) {
        int best = 5;
        int pr = get_prefix(l, r);
        // cout << "get_prefix = " << pr << '\n';
        if (pr != 0) {
            int k = r - l - pr;
            if ((r - l) % k == 0) {
                relax(best, 1);
            } else {
                relax(best, 2);
            }
        }
        relax(best, get_start(l, r));
        // pr = get_start(l, r);
        // // cout << "get_start = " << pr << '\n';
        // if (pr <= r) relax(best, 2);

        relax(best, get_center(l, r));
        // cout << "get_center = " << pr << '\n';
        return best;
    }
};

string s;
string rev_s;
int n;

cnt_tree cnt;
all_about_one_string al1;
all_about_one_string al2;

void make() {
    make_sparse();
    cnt = cnt_tree(s);
    al1 = all_about_one_string(s);
    al2 = all_about_one_string(rev_s);
}

int full_get(int l, int r) {
    vector<int> cnt1 = cnt.get(l, r);
    int best = 5;
    for (int i = 0; i < alf; i++) {
        if (cnt1[i] > 1) relax(best, 4);
    }
    if (best == 5) return -1;
    // cout << "cnt_ans_1 = " << best << '\n';
    if (cnt1[s[l] - 'a'] > 1) relax(best, 3);
    // cout << "cnt_ans_2 = " << best << '\n';
    if (cnt1[s[r - 1] - 'a'] > 1) relax(best, 3);
    // cout << "cnt_ans_3 = " << best << '\n';
    relax(best, al1.get(l, r));
    if (best <= 2) return best;
    // cout << "best = " << best;
    // cout << "al1_ans = " << best << '\n';
    relax(best, al2.get(n - r, n - l));
    return best - 6 * (best == 5);
}

void input() {
    cin >> n;
    cin >> s;
    for (int i = n - 1; i >= 0; i--) {
        rev_s += s[i];
    }
}

void solve() {
    int q;
    cin >> q;
    int l, r;
    for (int i = 0; i < q; i++) {
        cin >> l >> r;
        l--;
        cout << full_get(l, r) << '\n';
    }
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    input();
    // cout << "h1" << endl;
    make();
    // cout << "h2" << endl;
    solve();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define all(a) (a).begin(), (a).end()
#define pii pair <int, int>

const int maxn = 2e5 + 10;
const int logn = 17;
const int alf = 26;

int pw2[logn];
int lg2[maxn];

void make_sparse() {
    pw2[0] = 1;
    for (int i = 1; i < logn; i++) {
        pw2[i] = 2 * pw2[i - 1];
    }
    lg2[0] = -1;
    for (int i = 1; i < maxn; i++) {
        lg2[i] = lg2[i / 2] + 1;
    }
}

struct sparse_max {
    vector<vector<int>> table;
    int n;
    sparse_max() {}
    sparse_max(vector<int> &v) {
        n = v.size();

        int logn1 = 1;
        while (pw2[logn1] <= n) logn1++;
        table.resize(n, vector<int> (logn1));
        for (int i = 0; i < n; i++) {
            table[i][0] = v[i];
        }
        for (int c = 1; c < logn1; c++) {
            for (int i = 0; i < n; i++) {
                if (i + pw2[c - 1] < n) {
                    table[i][c] = max(table[i][c - 1], table[i + pw2[c - 1]][c - 1]);
                } else {
                    table[i][c] = table[i][c - 1];
                }
            }
        }
    }
    int get(int l, int r) {
        // полуинтервал
        if (r <= l) return 0;
        return max(table[l][lg2[r - l]], table[r - pw2[lg2[r - l]]][lg2[r - l]]);
    }
};

struct sparse_min {
    vector<vector<int>> table;
    int n;
    sparse_min() {}
    sparse_min(vector<int> &v) {
        n = v.size();
        int logn1 = 1;
        while (pw2[logn1] <= n) logn1++;
        table.resize(n, vector<int> (logn1));
        for (int i = 0; i < n; i++) {
            table[i][0] = v[i];
        }
        for (int c = 1; c < logn1; c++) {
            for (int i = 0; i < n; i++) {
                if (i + pw2[c - 1] < n) {
                    table[i][c] = min(table[i][c - 1], table[i + pw2[c - 1]][c - 1]);
                } else {
                    table[i][c] = table[i][c - 1];
                }
            }
        }
    }
    int get(int l, int r) {
        // полуинтервал
        if (r <= l) return maxn;
        return min(table[l][lg2[r - l]], table[r - pw2[lg2[r - l]]][lg2[r - l]]);
    }
};

struct cnt_tree {
    vector<vector<int>> tree;
    int n;
    cnt_tree() {}

    void make_cnt(vector<int> &v, char h) {
        v.resize(alf);
        v[h - 'a'] = 1;
    }

    void sum_cnt(vector<int> &v, vector<int> &l, vector<int> &r) {
        for (int i = 0; i < alf; i++) {
            v[i] = l[i] + r[i];
        }
    }

    void build(const string &s, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            make_cnt(tree[v], s[tl]);
            return;
        }
        int tm = (tl + tr) / 2;
        build(s, 2 * v + 1, tl, tm);
        build(s, 2 * v + 2, tm, tr);
        tree[v].resize(alf);
        sum_cnt(tree[v], tree[2 * v + 1], tree[2 * v + 2]);
    }

    cnt_tree(const string &s) {
        n = s.size();
        tree.resize(4 * n);
        build(s, 0, 0, n);
    }

    void get(vector<int> &ans, int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return;
        if (tl >= l && tr <= r) {
            sum_cnt(ans, ans, tree[v]);
            return;
        }
        int tm = (tl + tr) / 2;
        get(ans, 2 * v + 1, tl, tm, l, r);
        get(ans, 2 * v + 2, tm, tr, l, r);
    }

    vector<int> get(int l, int r) {
        vector<int> ans(alf);
        get(ans, 0, 0, n, l, r);
        return ans;
    }
};

struct min_tree {
    vector<int> tree;
    int n;
    min_tree() {}
    void build(vector<int> &a, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            tree[v] = a[tl];
            return;
        }
        int tm = (tl + tr) / 2;
        build(a, 2 * v + 1, tl, tm);
        build(a, 2 * v + 2, tm, tr);
        tree[v] = min(tree[2 * v + 1], tree[2 * v + 2]);
    }
    min_tree(vector<int> & a) {
        n = a.size();
        tree.resize(4 * n);
        build(a, 0, 0, n);
    }

    int get(int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return maxn;
        if (tl >= l && tr <= r) return tree[v];
        int tm = (tl + tr) / 2;
        return min(get(2 * v + 1, tl, tm, l, r), get(2 * v + 2, tm, tr, l, r));
    }

    int get(int l, int r) {
        return get(0, 0, n, l, r);
    }
};

struct max_tree {
    vector<int> tree;
    int n;
    max_tree() {}
    void build(vector<int> &a, int v, int tl, int tr) {
        if (tl + 1 == tr) {
            tree[v] = a[tl];
            return;
        }
        int tm = (tl + tr) / 2;
        build(a, 2 * v + 1, tl, tm);
        build(a, 2 * v + 2, tm, tr);
        tree[v] = max(tree[2 * v + 1], tree[2 * v + 2]);
    }
    max_tree(vector<int> & a) {
        n = a.size();
        tree.resize(4 * n);
        build(a, 0, 0, n);
    }

    int get(int v, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return 0;
        if (tl >= l && tr <= r) return tree[v];
        int tm = (tl + tr) / 2;
        return max(get(2 * v + 1, tl, tm, l, r), get(2 * v + 2, tm, tr, l, r));
    }

    int get(int l, int r) {
        return get(0, 0, n, l, r);
    }
};

vector<int> suff(string &s) {
    s += '$';
    int n = s.size();
    vector<int> cnt(27);
    for (int i = 0; i < n - 1; i++)
        cnt[s[i] - 'a']++;
    vector<int> pos(27);
    pos[0] = 1;
    for (int i = 1; i < 27; i++)
        pos[i] = pos[i - 1] + cnt[i - 1];
    vector<int> a(n);
    for (int i = 0; i < n - 1; i++)
        a[pos[s[i] - 'a']++] = i;
    a[0] = n - 1;
    vector<int> c(n);
    int cc = 0;
    for (int i = 0; i < n - 1; i++) {
        c[a[i]] = cc;
        if (s[a[i]] != s[a[i + 1]]) cc++;
    }
    c[a[n - 1]] = cc;
    cnt.resize(n);
    pos.resize(n);
    for (int l = 1; l < n; l *= 2) {
        cnt.assign(n, 0);
        for (int i = 0; i < n; i++)
            cnt[c[i]]++;
        pos[0] = 0;
        for (int i = 1; i < n; i++)
            pos[i] = pos[i - 1] + cnt[i - 1];
        vector<int> na(n);
        for (int i = 0; i < n; i++) {
            int ind = (a[i] - l + n) % n;
            na[pos[c[ind]]++] = ind;
        }
        a = na;

        vector<int> nc(n);
        cc = 0;
        for (int i = 0; i < n - 1; i++) {
            nc[a[i]] = cc;
            if (c[a[i]] != c[a[i + 1]] || c[(a[i] + l) % n]!= c[(a[i + 1] + l) % n]) cc++;
        }
        nc[a[n - 1]] = cc;
        c = nc;
    }
    // a.erase(a.begin());
    return a;
}

void relax(int &a, int b) {
    a = min(a, b);
}

void relax_mx(int &a, int b) {
    a = max(a, b);
}

vector<int> pos_create;

bool cmp(int a, int b) {
    return pos_create[a] < pos_create[b];
}

struct all_about_one_string {
    int n;
    string s;
    min_tree easy_tree;
    vector<int> suf;
    vector<int> lcp;
    vector<int> pos;
    sparse_min sparse_lcp;
    vector<int> for_st;

    int get_lcp(int a, int b) {
        a = pos[a];
        b = pos[b];
        if (a > b) swap(a, b);
        return sparse_lcp.get(a + 1, b + 1);
    }

    vector<vector<int>> mst;
    vector<vector<int>> left_right;
    vector<vector<int>> right_left;

    vector<vector<int>> le_ri_2;
    vector<vector<int>> ri_le_2;

    vector<max_tree> spmx;
    vector<min_tree> spmn;
    void build(int v, int tl, int tr) {
        if (tl + 1 == tr) {
            mst[v] = {tl};
            return;
        }
        int tm = (tl + tr) / 2;
        build(2 * v + 1, tl, tm);
        build(2 * v + 2, tm, tr);
        mst[v].resize(tr - tl);
        merge(all(mst[2 * v + 1]), all(mst[2 * v + 2]), mst[v].begin(), cmp);
        spmx[v] = max_tree(mst[v]);
        spmn[v] = min_tree(mst[v]);

        vector<pii> stack = {{0, -1}};
        left_right[v].resize(tr - tl);
        left_right[v][0] = -1;
        for (int i = 1; i < tr - tl; i++) {
            int lp = get_lcp(mst[v][i - 1], mst[v][i]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            left_right[v][i] = max(left_right[v][stack.back().first], spmx[v].get(stack.back().first, i) + lp);
            stack.push_back({i, lp});
        }

        // заполни, можно без бинпоисков
        stack = {{tr - tl - 1, -1}};
        right_left[v].resize(tr - tl);
        right_left[v][tr - tl - 1] = -1;
        for (int i = tr - tl - 2; i >= 0; i--) {
            int lp = get_lcp(mst[v][i], mst[v][i + 1]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            right_left[v][i] = max(right_left[v][stack.back().first], spmx[v].get(i + 1, stack.back().first + 1) + lp);
            stack.push_back({i, lp});
        }

        // аналогично

        stack = {{0, -maxn}};
        le_ri_2[v].resize(tr - tl);
        le_ri_2[v][0] = -maxn;
        for (int i = 1; i < tr - tl; i++) {
            int lp = get_lcp(mst[v][i - 1], mst[v][i]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            le_ri_2[v][i] = max(le_ri_2[v][stack.back().first], - spmn[v].get(stack.back().first, i) + lp);
            stack.push_back({i, lp});
        }

        // заполни, можно без бинпоисков
        stack = {{tr - tl - 1, -maxn}};
        ri_le_2[v].resize(tr - tl);
        ri_le_2[v][tr - tl - 1] = -maxn;
        for (int i = tr - tl - 2; i >= 0; i--) {
            int lp = get_lcp(mst[v][i], mst[v][i + 1]);
            while (stack.size() > 1 && stack.back().second >= lp) {
                stack.pop_back();
            }
            ri_le_2[v][i] = max(ri_le_2[v][stack.back().first], - spmn[v].get(i + 1, stack.back().first + 1) + lp);
            stack.push_back({i, lp});
        }
    }

    void make_mst() {
        mst.resize(4 * n);
        spmx.resize(4 * n);
        spmn.resize(4 * n);
        left_right.resize(4 * n);
        right_left.resize(4 * n);
        le_ri_2.resize(4 * n);
        ri_le_2.resize(4 * n);
        build(0, 0, n);
    }

    int get_inside(int v, int tl, int tr, int l, int r, bool pre) {
        int lll = -1;
        int rrr = tr - tl;
        while (lll + 1 < rrr) {
            int m = (lll + rrr) / 2;
            // cout << "m = " << m << endl;
            if (cmp(l - 1, mst[v][m])) {
                rrr = m;
            } else {
                lll = m;
            }
            // cout << "h" << endl;
        }

        // int p1 = upper_bound(all(mst[v]), l - 1, cmp) - mst[v].begin();
        int p1 = rrr;

        int eqr;
        if (p1 == tr - tl) {
            eqr = 0;
        } else {
            eqr = get_lcp(l - 1, mst[v][p1]);
        }

        int bl = p1;
        int br = tr - tl;
        while (bl + 1 < br) {
            int bm = (bl + br) / 2;
            if (get_lcp(mst[v][bm], l - 1) >= eqr) {
                bl = bm;
            } else {
                br = bm;
            }
        }

        int eql;
        if (p1 == 0) {
            eql = 0;
        } else {
            eql = get_lcp(l - 1, mst[v][p1 - 1]);
        }
        int bl1 = p1;
        int br1 = -1;
        while (br1 + 1 < bl1) {
            int bm = (bl1 + br1 + 1) / 2;
            if (get_lcp(mst[v][bm], l - 1) >= eql) {
                bl1 = bm;
            } else {
                br1 = bm;
            }
        }
        // cout << "h " << endl;
        // cout << bl1 << ' ' << p1 << endl;
        int ans = -maxn;
        if (pre == 1) {
            relax_mx(ans, spmx[v].get(bl1, p1) + eql);
            // cout << "ans = " << ans << endl;
            relax_mx(ans, spmx[v].get(p1, br) + eqr);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            if (bl1 >= 0) relax_mx(ans, left_right[v][bl1]);
            // cout << "ans = " << ans << endl;
            if (br != tr - tl) relax_mx(ans, right_left[v][bl]);
            // cout << "h " << endl;
            // cout << "ans for " << l - 1 << ' ' << tl << ' ' << tr << " = " << ans << endl;
            if (ans >= r) return 1;
            return 0;
        } else {
            relax_mx(ans, -spmn[v].get(bl1, p1) + eql);
            // cout << "ans = " << ans << endl;
            relax_mx(ans, -spmn[v].get(p1, br) + eqr);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            if (bl1 >= 0) relax_mx(ans, le_ri_2[v][bl1]);
            // cout << "ans = " << ans << endl;
            if (br != tr - tl) relax_mx(ans, ri_le_2[v][bl]);
            // cout << "ans = " << ans << endl;
            // cout << "h " << endl;
            // cout << "for " << l - 1 << ' ' << tl << ' ' << tr << " ans = " << ans << '\n';
            if (ans + l > 0) return 1;
            return 0;
        }
    }

    int get_prefix(int v, int tl, int tr, int l, int r) {
        // cout << "h = " << tl << ' ' << tr << ' ' << l << endl;
        if (tl >= r || tr <= l) return maxn;
        if (tl + 1 == tr) {
            // cout << "get_lcp(" << l << ' ' << tl << ") = " << get_lcp(l, tl) << '\n';
            if (get_lcp(l - 1, tl) + tl >= r) return tl;
            return maxn;
        }
        int tm = (tl + tr) / 2;
        if (tl >= l && tr <= r) {
            // переделать
            if (!get_inside(v, tl, tr, l, r, 1)) {
                // cout << "get1" << endl;
                return maxn;
            }
            // cout << "get2" << endl;
            int g1 = get_prefix(2 * v + 1, tl, tm, l, r);
            if (g1 != maxn) return g1;
            return get_prefix(2 * v + 2, tm, tr, l, r);
        }
        int g1 = get_prefix(2 * v + 1, tl, tm, l, r);
        if (g1 != maxn) return g1;
        return get_prefix(2 * v + 2, tm, tr, l, r);
    }

    int get_repeat(int v, int tl, int tr, int l) {
        // cout << "h = " << tl << ' ' << tr << endl;
        if (tr <= l) return maxn;
        if (tl + 1 == tr) {
            // cout << "get_lcp(" << l << ' ' << tl << ") = " << get_lcp(l, tl) << '\n';
            if (get_lcp(l - 1, tl) + l - 1 >= tl) return tl;
            return maxn;
        }
        int tm = (tl + tr) / 2;
        if (tl >= l) {
            // переделать
            // cout << "get_inside " << v << ' ' << tl << ' ' << tr << ' ' << l << endl;
            if (!get_inside(v, tl, tr, l, 0, 0)) {
                // cout << "geted1" << endl;
                return maxn;
            }
            // cout << "geted2" << endl;
            int g1 = get_repeat(2 * v + 1, tl, tm, l);
            if (g1 != maxn) return g1;
            return get_repeat(2 * v + 2, tm, tr, l);
        }
        int g1 = get_repeat(2 * v + 1, tl, tm, l);
        if (g1 != maxn) return g1;
        return get_repeat(2 * v + 2, tm, tr, l);
    }

    int get_prefix(int l, int r) {
        int g = get_prefix(0, 0, n, l + 1, r);
        // cout << "g = " << g << '\n';
        if (g == maxn) return 0;
        // cout << "g = " << g << '\n';
        return r - g;
    }

    int get_start(int l, int r) {
        if (for_st[l] <= r) return 2;
        return 5;
    }

    void make_center() {
        for_st.resize(n, maxn);
        // cout << "here = make_center" << endl;
        for (int l = 0; l < n; l++) {
            // cout << l << endl;
            // cout << "l = " << l << endl;
            for_st[l] = 2 * get_repeat(0, 0, n, l + 1) - l;
        }

        easy_tree = min_tree(for_st);
    }

    int get_center(int l, int r) {
        int r1 = easy_tree.get(l, r);
        if (r1 <= r) return 3;
        return 5;
    }

    all_about_one_string() {}
    all_about_one_string(string s_) {
        s = s_;
        suf = suff(s);
        n = s.size();

        pos.resize(n);
        for (int i = 0; i < n; i++) {
            pos[suf[i]] = i;
        }
        pos_create = pos;

        lcp.resize(n);
        int last = 0;
        for (int i = 0; i < n - 1; i++) {
            int j = pos[i];
            lcp[j] = last;
            for (int p = last; ; p++) {
                if (s[i + p] == s[suf[j - 1] + p]) {
                    lcp[j]++;
                } else {
                    break;
                }
            }
            last = max(0, lcp[j] - 1);
        }

        sparse_lcp = sparse_min(lcp);
        // cout << "here" << endl;
        // cout << "make mst" << endl;
        make_mst();
        // cout << "make center" << endl;
        // cout << "here" << endl;
        make_center();
        // cout << "finished" << endl;
        // cout << get_lcp(0, 3) << '\n';
    }

    int get(int l, int r) {
        int best = 5;
        int pr = get_prefix(l, r);
        // cout << "get_prefix = " << pr << '\n';
        if (pr != 0) {
            int k = r - l - pr;
            if ((r - l) % k == 0) {
                relax(best, 1);
            } else {
                relax(best, 2);
            }
        }
        relax(best, get_start(l, r));
        // pr = get_start(l, r);
        // // cout << "get_start = " << pr << '\n';
        // if (pr <= r) relax(best, 2);

        relax(best, get_center(l, r));
        // cout << "get_center = " << pr << '\n';
        return best;
    }
};

string s;
string rev_s;
int n;

cnt_tree cnt;
all_about_one_string al1;
all_about_one_string al2;

void make() {
    make_sparse();
    cnt = cnt_tree(s);
    al1 = all_about_one_string(s);
    al2 = all_about_one_string(rev_s);
}

int full_get(int l, int r) {
    vector<int> cnt1 = cnt.get(l, r);
    int best = 5;
    for (int i = 0; i < alf; i++) {
        if (cnt1[i] > 1) relax(best, 4);
    }
    if (best == 5) return -1;
    // cout << "cnt_ans_1 = " << best << '\n';
    if (cnt1[s[l] - 'a'] > 1) relax(best, 3);
    // cout << "cnt_ans_2 = " << best << '\n';
    if (cnt1[s[r - 1] - 'a'] > 1) relax(best, 3);
    // cout << "cnt_ans_3 = " << best << '\n';
    relax(best, al1.get(l, r));
    // cout << "best = " << best;
    // cout << "al1_ans = " << best << '\n';
    relax(best, al2.get(n - r, n - l));
    return best - 6 * (best == 5);
}

void input() {
    cin >> n;
    cin >> s;
    for (int i = n - 1; i >= 0; i--) {
        rev_s += s[i];
    }
}

void solve() {
    int q;
    cin >> q;
    int l, r;
    for (int i = 0; i < q; i++) {
        cin >> l >> r;
        l--;
        cout << full_get(l, r) << '\n';
    }
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    input();
    // cout << "h1" << endl;
    make();
    // cout << "h2" << endl;
    if (n > 100000) return 0;
    solve();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <memory.h>
#include <math.h>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <stdio.h>
#include <queue>
//#include <stack>
#include <cstdio>
#include <bitset>

using namespace std;

#define nfs ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define f first
#define s second
#define m_p make_pair
#define pb push_back
#define ii pair<int,int>
#define iii pair<int,pair<int,int> >
#define ll long long
#define ull unsigned long long
#define ld long double
#define ef else if
#define loc(x) (x).begin(),(x).end()
#define locR(x) (x).rbegin(),(x).rend()
#define no puts("NO")
#define yes puts("YES")
#define ex puts("-1")
#define en puts("")
#define _ cout
#define __ <<
#define outV(v) for(int i = 0 ; i < v.size() ; i++)cout << v[i] << ' ';
#define outA(x,l,r) for(int i = l ; i < r ; i++)cout << x[i] << ' ';

#ifndef ONLINE_JUDGE
#define scanf scanf_s
#endif

const ld EPS = 1e-18;
const double DEPS = 1e-9;
const ld PI = 3.141592653589793238;
const ll MOD = 998244353;
const int N = (int)(5e5) + 10;

void inp()
{
#ifndef ONLINE_JUDGE
	FILE* stream;
	freopen_s(&stream, "inp.txt", "r", stdin);
#endif
}

void out()
{
#ifndef ONLINE_JUDGE
	FILE* stream;
	freopen_s(&stream, "out.txt", "w", stdout);
#endif
}

ll gcd(ll fx, ll fy)
{
	if (!fy) return fx;
	return gcd(fy, fx % fy);
}

inline void fill(int* ar, int sz, int val)
{
	for (int i = 0; i < sz; i++)
	{
		ar[i] = val;
	}
}

ll ans;

int main()
{
	inp();
	int n;
	cin >> n;

	for (int i = 0; i < n; i++)
	{
		if (i % 2 == 0 && i + 1 < n)
		{
			ans++;
		}
		else if(i % 2 && i + 2 < n)
		{
			ans += ((i + 1) & -(i + 1));
		}
	}

	if (n % 2)
	{
		ll mn = 1e18;
		for (int i = 0; i < n - 1; i++)
		{
			mn = min(1ll * (n - 1) ^ i, mn);
		}
		ans += mn;
	}
	cout << ans;

}


//  MONSTER >_<
#include <bits/stdc++.h>
#define SPEED ios::sync_with_stdio(false); cin.tie(0)
#define loop(i,a,b) for(int i=a;i<b;i++)
#define ll long long
#define vi vector<int>
#define vl vector<ll>
#define pii pair<int,int>
#define pll pair<long long int,long long int>
#define ff first
#define ss second
#define mp make_pair
#define pb push_back
#define mo 1000000007
#define inf 1e18
#define eps 0.0000000001
#define stp setprecision(20)
#define all(v) v.begin(),v.end()
#define endl '\n'
using namespace std;
//mt19937 rng32(chrono::steady_clock::now().time_since_epoch().count());

#define N  int(2e5)+10

int main()
{    SPEED;

    ll n;
    cin>>n;
ll ans=0;n--;
    for(ll i=0;(1<<i)<=n;i++){
    	 ll v=1LL*(1<<i),f  =(((n-v)/(2*v))+1);ans+=f*v;
    }
    cout<<ans;
}


#include <bits/stdc++.h>
#define ll long long
#define re return
using namespace std;
ll f(ll n){
    if (n==2) re 0;
    if (n==4) re 2;
    re f(n/2)*2+n/2;
}
int main(){
    ll n;
    cin >> n;
    ll ans;
    ans=n/2;
    if (n%2==1) n++;
    ll tmp=0;
    ll step=1;
    while(step<n) step*=2;
    if (step==n){
        cout << f(n)+ans;
        re 0;
    }
    ans+=f(step);
    tmp=step-n; tmp+=2;
    while (tmp<step/2){
        ans-=f(step/2);
        tmp-=step/2;
        step/=2;
    }
    if (tmp!=0) ans-=f(step/2);
    cout << ans;
    re 0;
}


#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

typedef long long ll;

int main(){
	//	freopen("in.in", "r", stdin);freopen("out.out", "w", stdout);
	ios::sync_with_stdio(false);
	ll n;
	cin >> n;
	ll res = 0;
	ll cost = 1;
	while (n > 0){
		res += cost * (n / 2);
		n = n / 2 + n % 2;
		cost *= 2;
	}
	cout << res;

	return 0;
}


#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
using namespace std;
int x[4][2], y[4][2];
void ret(int xx){
	if(xx) puts("YES");
	else puts("NO");
	exit(0);
}
int f(int idx, int sq){
		int X = x[idx][1-sq], Y = y[idx][1-sq];
		int x1 = x[0][sq], x2 = x[0][sq];
		for(int i = 1; i < 4;  i ++) x1 = min(x1,x[i][sq]);
		for(int i = 1; i < 4;  i ++) x2 = max(x2,x[i][sq]);
		if(X < x1 or X > x2) return 0;
		int y1 = y[0][sq], y2 = y[0][sq];
		for(int i = 1; i < 4;  i ++) y1 = min(y1,y[i][sq]);
		for(int i = 1; i < 4;  i ++) y2 = max(y2,y[i][sq]);
		if(Y < y1 or Y > y2) return 0;
		return 1;
}
int main(){
	for(int j = 0; j < 2; j ++)
		for(int i = 0; i < 4; i ++ ) scanf("%d %d", &x[i][j], &y[i][j]);

	for(int i = 0; i < 4; i ++){
		if(f(i,0)) ret(1);
		if(f(i,1)) ret(1);
	}
	ret(0);
}


#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define oo 2000000000
int x[2][6] , y[2][6];
int cur[2] = {5,4};

struct Point{
    int x , y;
};

bool onSegment(Point p, Point q, Point r)
{
    if (q.x <= max(p.x, r.x) && q.x >= min(p.x, r.x) &&
        q.y <= max(p.y, r.y) && q.y >= min(p.y, r.y))
       return true;

    return false;
}

int orientation(Point p, Point q, Point r)
{
    // See https://www.geeksforgeeks.org/orientation-3-ordered-points/
    // for details of below formula.
    int val = (q.y - p.y) * (r.x - q.x) -
              (q.x - p.x) * (r.y - q.y);

    if (val == 0) return 0;  // colinear

    return (val > 0)? 1: 2; // clock or counterclock wise
}

bool doIntersect(Point p1, Point q1, Point p2, Point q2)
{
    // Find the four orientations needed for general and
    // special cases
    int o1 = orientation(p1, q1, p2);
    int o2 = orientation(p1, q1, q2);
    int o3 = orientation(p2, q2, p1);
    int o4 = orientation(p2, q2, q1);

    // General case
    if (o1 != o2 && o3 != o4)
        return true;

    // Special Cases
    // p1, q1 and p2 are colinear and p2 lies on segment p1q1
    if (o1 == 0 && onSegment(p1, p2, q1)) return true;

    // p1, q1 and q2 are colinear and q2 lies on segment p1q1
    if (o2 == 0 && onSegment(p1, q2, q1)) return true;

    // p2, q2 and p1 are colinear and p1 lies on segment p2q2
    if (o3 == 0 && onSegment(p2, p1, q2)) return true;

     // p2, q2 and q1 are colinear and q1 lies on segment p2q2
    if (o4 == 0 && onSegment(p2, q1, q2)) return true;

    return false; // Doesn't fall in any of the above cases
}

bool check(int xx,int yy,int i){
        Point A;
        A.x = xx;
        A.y = yy;
        Point B;
        B.x = 200;
        B.y = yy;
        bool can[4] = {0};
        for(int j=0;j<4;j++){
            Point C;
            Point D;
            C.x = x[i][j];
            C.y = y[i][j];
            D.x = x[i][(j + 1) % 4];
            D.y = y[i][(j + 1) % 4];
            if(doIntersect(A,B,C,D))
                can[j] = true;
        }
        return ((can[0] || can[1] || can[2] || can[3]) ^ ((can[0] && can[2]) || (can[1] && can[3])));
}

int main(){
    for(int i=1;i>=0;i--){
        for(int j=0;j<4;j++){
            scanf("%d%d",&x[i][j],&y[i][j]);
        }
    }
    x[0][4] = (x[0][0] + x[0][2]) / 2;
    y[0][4] = (y[0][0] + y[0][2]) / 2;
    for(int i=1;i>=0;i--){
        for(int j=0;j<cur[i];j++){
            if(check(x[i][j],y[i][j],i ^ 1)){
                puts("YES");
                return 0;
            }
        }
    }
    puts("NO");
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
struct P{double x,y;};
struct rua
{
	double u,d,l,r;
	P f[4];
	void init()
	  {
	  u=r=-500;
	  l=d=500;
	  }
}a,b;
double x,y;
bool in(P a,P b,P c,P d)
{
	return min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&&min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y);
}
bool check(int i,int j)
{
	P A=a.f[i];
	P B=a.f[(i+1)%4];
	P C=b.f[j];
	P D=b.f[(j+1)%4];
	return in(A,B,C,D);
}
int main()
{
	a.init(),b.init();
	for(int i=0;i<4;i++)
	  {
	  scanf("%lf%lf",&x,&y);
	  a.u=max(a.u,y);
	  a.d=min(a.d,y);
	  a.l=min(a.l,x);
	  a.r=max(a.r,x);
	  }
	a.f[0]={a.l,a.u};
	a.f[1]={a.r,a.u};
	a.f[2]={a.r,a.d};
	a.f[3]={a.l,a.d};
	for(int i=0;i<4;i++)
	  {
	  scanf("%lf%lf",&x,&y);
	  b.u=max(b.u,x+y);
	  b.d=min(b.d,x+y);
	  b.l=min(b.l,x-y);
	  b.r=max(b.r,x-y);
	  }
	b.f[0]={(b.u+b.r)/2.0,(b.u-b.r)-2.0};
	b.f[1]={(b.u+b.l)/2.0,(b.u-b.l)-2.0};
	b.f[2]={(b.d+b.l)/2.0,(b.d-b.l)-2.0};
	b.f[3]={(b.d+b.r)/2.0,(b.d-b.r)-2.0};
	for(int i=0;i<4;i++)
	  for(int j=0;j<4;j++)
	    if(check(i,j))return printf("YES\n"),0;
	return printf("NO\n"),0;
}