import java.io.*
import java.util.*

fun main() {
    val solver = Solver(System.`in`, System.out)
    solver.solve()
    solver.clear()
}

class Solver(input: InputStream, output: OutputStream) {

    companion object {
        private const val MAX_N = (1e6 + 10).toInt()
        private const val INF = (1e9 + 7).toInt()
        private const val MOD = (1e9 + 7).toInt()
        private const val INF_F = 1e-6
    }

    private val reader = Reader(input)
    private val writer = Writer(output)

    fun solve() {
        repeat(reader.nextInt()) {
            val n = reader.nextInt()
            val s = reader.nextArrayInt(n)

            if (n == 1) {
                writer.println(if (s.first() == 2048) "YES" else "NO")
                return@repeat
            }

            val q = PriorityQueue<Int>(Comparator<Int> { o1, o2 ->
                return@Comparator o1.compareTo(o2)
            })

            q.addAll(s.toList())

            while (q.isNotEmpty() && q.first() < 2048) {
                val x = q.poll()
                if (q.isEmpty()) {
                    writer.println("NO")
                    return@repeat
                }
                val y = q.poll()

                if (x != y) {
                    q.add(y)
                    continue
                }

                q.add(x + y)
            }

            writer.println(if (q.isNotEmpty() && q.first() == 2048) "YES" else "NO")
        }
    }

    fun clear() {
        writer.close()
    }

    private fun IntArray.gcd(): Int {
        var g = first()
        forEach { g = gcd(g, it) }
        return g
    }

    private fun LongArray.gcd(): Long {
        var g = first()
        forEach { g = gcd(g, it) }
        return g
    }

    private fun gcd(a: Int, b: Int): Int {
        return if (b == 0) a else gcd(b, a % b)
    }

    private fun gcd(a: Long, b: Long): Long {
        return if (b == 0L) a else gcd(b, a % b)
    }
}

class Reader(input: InputStream) {
    private val reader = BufferedReader(InputStreamReader(BufferedInputStream(input)), 32768)
    private var tokenizer: StringTokenizer? = null

    fun next(): String {
        while (tokenizer == null || !tokenizer!!.hasMoreTokens()) {
            try {
                tokenizer = StringTokenizer(reader.readLine())
            } catch (e: IOException) {
                throw RuntimeException(e)
            }
        }
        return tokenizer!!.nextToken()
    }

    fun nextInt() = next().toInt()

    fun nextLong() = next().toLong()

    fun nextArrayInt(count: Int): IntArray {
        return nextArrayInt(0, count)
    }

    fun nextArrayInt(start: Int, count: Int): IntArray {
        val a = IntArray(start + count)
        for (i in start until start + count) {
            a[i] = nextInt()
        }
        return a
    }

    fun nextArrayLong(count: Int): LongArray {
        val a = LongArray(count)
        for (i in 0 until count) {
            a[i] = nextLong()
        }
        return a
    }

    fun nextIntPair(): Pair<Int, Int> {
        val x = nextInt()
        val y = nextInt()
        return x to y
    }
}

class Writer(output: OutputStream) {
    private val writer = PrintWriter(BufferedOutputStream(output))

    fun <T> print(t: T) = writer.print(t)
    fun println() = writer.println()
    fun <T> println(t: T) = writer.println(t)

    fun printBooleanArray(array: BooleanArray) = printIntArray(array.map { if (it) 1 else 0 }.toIntArray())
    fun printIntArray(array: IntArray) = array.joinToString(" ").let(writer::println)
    fun printLongArray(array: LongArray) = array.joinToString(" ").let(writer::println)
    fun printCharArray(array: CharArray) = array.joinToString("").let(writer::println)

    fun close() = writer.close()
    fun flush() = writer.flush()
}


import java.io.PrintWriter
import java.util.PriorityQueue
import java.util.StringTokenizer

fun main() {
    output {
        val q = readInt()

        repeat(q) {
            val n = readInt()
            val S = readInts(n)

            var sum = 0
            val ans = run {
                for (s in S) {
                    if(s > 2048) continue
                    sum += s
                    if(sum >= 2048) return@run true
                }

                false
            }

            println(if(ans) "YES" else "NO")
        }
    }
}

/** IO code start */
@JvmField val _reader = System.`in`.bufferedReader()
fun readLine(): String? = _reader.readLine()
fun readLn() = _reader.readLine()!!
@JvmField var _tokenizer: StringTokenizer = StringTokenizer("")
fun read(): String {
    while (_tokenizer.hasMoreTokens().not()) _tokenizer = StringTokenizer(_reader.readLine() ?: return "", " ")
    return _tokenizer.nextToken()
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }

@JvmField val _writer = PrintWriter(System.out, false)
inline fun output(block: PrintWriter.()->Unit) { _writer.apply(block).flush() }
fun iprintln(o: Any?) { println(o) } // immediate println for interactive, bypasses output{} blocks


import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*

fun main() {
    Scanner(BufferedReader(InputStreamReader(System.`in`))).use { scanner ->
        val q = scanner.nextInt()
        val sb = StringBuffer()
        for (i in 0 until q) {
            val n = scanner.nextInt()
            val arr = BooleanArray(20)
            var flag = false
            for (j in 0 until n ) {
                val s = scanner.nextInt()
                if (s > 2048) continue
                var x = when (s) {
                    1->0
                    2->1
                    4->2
                    8->3
                    16->4
                    32->5
                    64->6
                    128->7
                    256->8
                    512->9
                    1024->10
                    2048->11
                    else -> 0
                }
                while (arr[x] && x < 11) {
                    arr[x] = false
                    x++
                }
                if (x == 11) {
                    flag = true
                } else {
                    arr[x] = true
                }
            }
            sb.append(if (flag) "YES\n" else "NO\n")
        }

        println(sb.toString())
    }
}


fun main() {
    var q = readLine()!!.toInt()
    while (q-- > 0) {
        val n = readLine()!!.toInt() - 1
        val a: MutableList<Int> = readLine()!!.split(' ').map{ it.toInt() }.toMutableList()
        var can = false
        var mv = true
        while (mv) {
            mv = false
            for (i in 0..n) {
                for (j in 0..n) {
                    if (i != j && a[i] == a[j] && a[i] != 0) {
                        a[i] = 2 * a[i]
                        a[j] = 0
                        mv = true
                        if (a[i] / 2 == 2048)
                            can = true;
                    }
                    if (a[i] == 2048)
                        can = true
                }
            }
        }
        println(when(can) {
            true -> "YES"
            false -> "NO"
        })
    }
}


fun main(){
    var q = readLine()!!.toInt()
    val map = HashMap<Int,Int>().withDefault { 0 }
    while (q>0){
        map.clear();q--;readLine()
        val arr = readLine()!!.split(" ").map { it.toInt() }
        for(i in arr)
            map[i] = map.getOrDefault(i,0)+1
        var pow = 1
        while (pow<=2048){
            map[pow*2] = map.getOrDefault(pow*2,0)+(map.getOrDefault(pow,0)/2)
            pow*=2
        }
        when (map.getOrDefault(2048,0) >=1){true-> println("YES") else-> println("NO")}
    }
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],tr[N],el[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int vis[N],fl[N];
int nw,tot;
inline void doit() {
    int p=nxt[0];
    int op=1;
    ++tot;
    while (p!=0&&p!=n+1) {
        /*cerr<<p<<endl;*/
        ++nw;
        if (vis[p]==0) vis[p]=tot;
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        if (op==1) tr[p]=min(tr[p],nw);
        else {
            tl[p]=min(tl[p],nw);
            if (vis[p]==tot) fl[p]=max(fl[p],nw);
        }
        p=(op==-1)?pre[p]:nxt[p];
    }
    /*
    if (p==n+1) {
        if (tl[n+1]!=0x3f3f3f3f) return;
        ++nw;
        tl[n+1]=min(tl[n+1],nw);
    }
    if (p==0) {
        if (tr[0]!=0x3f3f3f3f) return;
        ++nw;
        tr[0]=min(tr[0],nw);
    }*/
}
void init() {
    fil(tl,0x3f);
    fil(tr,0x3f);
    // tr[0]=0;
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nxt[0]!=n+1&&nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    while (q--) {
        int l=read(),r=read();
        if (tr[l]==0x3f3f3f3f) {
            rep (i,0,SIZ-1) printf("%d ",0);
            puts("");
            continue;
        }
        int *t=sum[tr[l]-1],*s;
        int pl=l;
        rep (i,l,r) if (fl[i]>fl[pl]&&vis[i]==vis[l]) pl=i;
        else if (vis[l]!=vis[i]) break;
        // cerr<<fl[pl]<<endl;
        if (fl[pl]!=0&&fl[pl]<tr[r]) s=sum[fl[pl]];
        else s=sum[tr[r]];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],tr[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int nw;
inline void doit() {
    int p=nxt[0];
    int op=1;
    while (p!=0&&p!=n+1) {
        ++nw;
        if (op==1) tl[p]=min(tl[p],nw);
        if (op==-1) tr[p]=min(tr[p],nw);
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        p=(op==-1)?pre[p]:nxt[p];
    }
    if (p==n+1) {
        ++nw;
        tl[n+1]=min(tl[n+1],nw);
    }
}
void init() {
    fil(tl,0x3f);
    fil(tr,0x3f);
    // tr[0]=0;
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        doit();
        if ((s[nxt[0]]=='<'||s[nxt[0]]=='>')&&nxt[nxt[0]]==n+1) break;
    }
}
int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    while (q--) {
        int l=read(),r=read();
        // cerr << l << " " << r << endl;
        int *t=sum[tl[l]-1],*s;
        // cerr<<tr[l-1]<<" "<<tl[r+1]<<endl;
        if (tr[l-1]<tl[r+1]) s=sum[tr[l-1]-1];
        else s=sum[tl[r+1]-1];
        //cerr<<tl[l]<<endl;
        //cerr<<s[0]<<" "<<t[0]<<endl;
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define pb push_back
#define all(v) v.begin(),v.end()
#define siz(x) ((int)x.size())
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
typedef vector<int> vi;
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],tr[N],el[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int vis[N],fl[N];
int nw,tot;
inline void doit() {
    int p=nxt[0];
    int op=1;
    ++tot;
    while (p!=0&&p!=n+1) {
        /*cerr<<p<<endl;*/
        ++nw;
        if (vis[p]==0) vis[p]=tot;
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        if (op==1) tr[p]=min(tr[p],nw);
        else {
            tl[p]=min(tl[p],nw);
            if (vis[p]==tot) fl[p]=max(fl[p],nw);
        }
        p=(op==-1)?pre[p]:nxt[p];
    }
    /*
    if (p==n+1) {
        if (tl[n+1]!=0x3f3f3f3f) return;
        ++nw;
        tl[n+1]=min(tl[n+1],nw);
    }
    if (p==0) {
        if (tr[0]!=0x3f3f3f3f) return;
        ++nw;
        tr[0]=min(tr[0],nw);
    }*/
}
void init() {
    fil(tl,0x3f);
    fil(tr,0x3f);
    // tr[0]=0;
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nxt[0]!=n+1&&nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
struct Qry {
#define mid ((ll+rr)>>1)
#define lc o<<1,ll,mid
#define rc o<<1|1,mid+1,rr
    vi v,t;
    void ins(int x) {
        v.pb(x);
    }
    void build(int o,int ll,int rr) {
        if (ll==rr) {
            t[o]=fl[v[ll]];
            return;
        }
        build(lc),build(rc);
        t[o]=max(t[o<<1],t[o<<1|1]);
    }
    int qry(int o,int ll,int rr,int l,int r) {
        if (ll>=l&&rr<=r) return t[o];
        int ans=0;
        if (l<=mid) ans=max(ans,qry(lc,l,r));
        if (r>mid) ans=max(ans,qry(rc,l,r));
        return ans;
    }
    void init() {
        if (siz(v)==0) return;
        t.resize(siz(v)*4);
        build(1,0,siz(v)-1);
    }
    int get(int l,int r) {
        int ll=lower_bound(all(v),l)-v.begin();
        int rr=upper_bound(all(v),r)-v.begin()-1;
        /*rep (i,ll,rr) cerr<<v[i]<<" ";cerr<<endl;*/
        return qry(1,0,siz(v)-1,ll,rr);
    }
} w[N];

int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    rep (i,1,n) w[vis[i]].ins(i);
    rep (i,1,tot) w[i].init();
    while (q--) {
        int l=read(),r=read();
        if (tr[l]==0x3f3f3f3f) {
            rep (i,0,SIZ-1) printf("%d ",0);
            puts("");
            continue;
        }
        int *t=sum[tr[l]-1],*s;
        int pl=w[vis[l]].get(l,r);
        /*cerr<<pl<<endl;
        cerr<<tr[l]<<endl;*/
        pl=min(pl,tl[l]);
        /*rep (i,l,r) if (fl[i]>fl[pl]&&vis[i]==vis[l]) pl=i;*/
        // cerr<<fl[pl]<<endl;
        if (pl!=0&&pl<tr[r]) s=sum[pl];
        else s=sum[tr[r]];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define pb push_back
#define all(v) v.begin(),v.end()
#define siz(x) ((int)x.size())
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
#define per(i,a,n) for (int i=(n);i>=(a);--i)
typedef vector<int> vi;
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],fi[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int nw,tot;
inline void doit() {
    int p=nxt[0];
    int op=1;
    while (p!=0&&p!=n+1) {
        ++nw;
        if (fi[p]==0) fi[p]=nw;
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        if (op==-1) tl[p]=min(tl[p],nw);
        p=(op==-1)?pre[p]:nxt[p];
    }
    if (p==0&&fi[p]==0) fi[p]=++nw;
    if (p==n+1&&fi[p]==0) fi[p]=++nw;
}
void init() {
    // tr[0]=0;
    fil(tl,0x3f);
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nxt[0]!=n+1&&nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    while (q--) {
        int l=read(),r=read();
        if (fi[l]==0x3f3f3f3f) {
            rep (i,0,SIZ-1) printf("%d ",0);
            puts("");
            continue;
        }
        int *t=sum[fi[l]-1],*s;
        // cerr<<fi[l]<<" "<<endl;
        // cerr<<tl[l]<<" "<<fi[r+1]<<endl;
        if (tl[l]<fi[r+1]) s=sum[tl[l]];
        else s=sum[fi[r+1]];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],tr[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int nw;
inline void doit() {
    int p=nxt[0];
    int op=1;
    while (p!=0&&p!=n+1) {
        // cerr<<p<<endl;
        ++nw;
        if (op==1) tl[p]=min(tl[p],nw);
        if (op==-1) tr[p]=min(tr[p],nw);
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        p=(op==-1)?pre[p]:nxt[p];
    }
    if (p==n+1) {
        if (tl[n+1]!=0x3f3f3f3f) return;
        ++nw;
        tl[n+1]=min(tl[n+1],nw);
    }
    if (p==0) {
        if (tr[0]!=0x3f3f3f3f) return;
        ++nw;
        tr[0]=min(tr[0],nw);
    }
}
void init() {
    fil(tl,0x3f);
    fil(tr,0x3f);
    // tr[0]=0;
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    while (q--) {
        int l=read(),r=read();
        int *t=sum[tl[l]-1],*s;
        if (tr[l-1]<tl[r+1]) s=sum[tr[l-1]-1];
        else s=sum[tl[r+1]-1];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define pb push_back
#define all(v) v.begin(),v.end()
#define siz(x) ((int)x.size())
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
typedef vector<int> vi;
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],tr[N],el[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int vis[N],fl[N];
int nw,tot;
inline void doit() {
    int p=nxt[0];
    int op=1;
    ++tot;
    while (p!=0&&p!=n+1) {
        /*cerr<<p<<endl;*/
        ++nw;
        if (vis[p]==0) vis[p]=tot;
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        if (op==1) tr[p]=min(tr[p],nw);
        else {
            tl[p]=min(tl[p],nw);
            if (vis[p]==tot) fl[p]=max(fl[p],nw);
        }
        p=(op==-1)?pre[p]:nxt[p];
    }
    /*
    if (p==n+1) {
        if (tl[n+1]!=0x3f3f3f3f) return;
        ++nw;
        tl[n+1]=min(tl[n+1],nw);
    }
    if (p==0) {
        if (tr[0]!=0x3f3f3f3f) return;
        ++nw;
        tr[0]=min(tr[0],nw);
    }*/
}
void init() {
    fil(tl,0x3f);
    fil(tr,0x3f);
    // tr[0]=0;
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nxt[0]!=n+1&&nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
struct Qry {
#define mid ((ll+rr)>>1)
#define lc o<<1,ll,mid
#define rc o<<1|1,mid+1,rr
    vi v,t;
    void ins(int x) {
        v.pb(x);
    }
    void build(int o,int ll,int rr) {
        if (ll==rr) {
            t[o]=fl[v[ll]];
            return;
        }
        build(lc),build(rc);
        t[o]=max(t[o<<1],t[o<<1|1]);
    }
    int qry(int o,int ll,int rr,int l,int r) {
        if (ll>=l&&rr<=r) return t[o];
        int ans=0;
        if (l<=mid) ans=max(ans,qry(lc,l,r));
        if (r>mid) ans=max(ans,qry(rc,l,r));
        return ans;
    }
    void init() {
        if (siz(v)==0) return;
        t.resize(siz(v)*4);
        build(1,0,siz(v)-1);
    }
    int get(int l,int r) {
        int ll=lower_bound(all(v),l)-v.begin();
        int rr=upper_bound(all(v),r)-v.begin()-1;
        rep (i,ll,rr) cerr<<v[i]<<" ";cerr<<endl;
        return qry(1,0,siz(v)-1,ll,rr);
    }
} w[N];

int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    rep (i,1,n) w[vis[i]].ins(i);
    rep (i,1,tot) w[i].init();
    while (q--) {
        int l=read(),r=read();
        if (tr[l]==0x3f3f3f3f) {
            rep (i,0,SIZ-1) printf("%d ",0);
            puts("");
            continue;
        }
        int *t=sum[tr[l]-1],*s;
        int pl=w[vis[l]].get(l,r);
        /*cerr<<pl<<endl;
        cerr<<tr[l]<<endl;*/
        pl=min(pl,tl[l]);
        /*rep (i,l,r) if (fl[i]>fl[pl]&&vis[i]==vis[l]) pl=i;*/
        // cerr<<fl[pl]<<endl;
        if (pl!=0&&pl<tr[r]) s=sum[pl];
        else s=sum[tr[r]];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define pb push_back
#define all(v) v.begin(),v.end()
#define siz(x) ((int)x.size())
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
typedef vector<int> vi;
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=2e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],tr[N],el[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int vis[N],fl[N];
int nw,tot;
inline void doit() {
    int p=nxt[0];
    int op=1;
    ++tot;
    while (p!=0&&p!=n+1) {
        /*cerr<<p<<endl;*/
        ++nw;
        if (vis[p]==0) vis[p]=tot;
        if (isdigit(s[p])) {
            if (s[p]=='0') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            if (s[stp]=='<'||s[stp]=='>') {
                pre[nxt[p]]=pre[p];
                nxt[pre[p]]=nxt[p];
            }
        }
        if (op==1) tr[p]=min(tr[p],nw);
        else {
            tl[p]=min(tl[p],nw);
            if (vis[p]==tot) fl[p]=max(fl[p],nw);
        }
        p=(op==-1)?pre[p]:nxt[p];
    }
    /*
    if (p==n+1) {
        if (tl[n+1]!=0x3f3f3f3f) return;
        ++nw;
        tl[n+1]=min(tl[n+1],nw);
    }
    if (p==0) {
        if (tr[0]!=0x3f3f3f3f) return;
        ++nw;
        tr[0]=min(tr[0],nw);
    }*/
}
void init() {
    fil(tl,0x3f);
    fil(tr,0x3f);
    // tr[0]=0;
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nxt[0]!=n+1&&nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
struct Qry {
#define mid ((ll+rr)>>1)
#define lc o<<1,ll,mid
#define rc o<<1|1,mid+1,rr
    vi v,t;
    void ins(int x) {
        v.pb(x);
    }
    void build(int o,int ll,int rr) {
        if (ll==rr) {
            t[o]=fl[v[ll]];
            return;
        }
        build(lc),build(rc);
        t[o]=max(t[o<<1],t[o<<1|1]);
    }
    int qry(int o,int ll,int rr,int l,int r) {
        if (ll>=l&&rr<=r) return t[o];
        int ans=0;
        if (l<=mid) ans=max(ans,qry(lc,l,r));
        if (r>mid) ans=max(ans,qry(rc,l,r));
        return ans;
    }
    void init() {
        if (siz(v)==0) return;
        t.resize(siz(v)*4);
        build(1,0,siz(v)-1);
    }
    int get(int l,int r) {
        int ll=lower_bound(all(v),l)-v.begin();
        int rr=upper_bound(all(v),r)-v.begin()-1;
        return qry(1,0,siz(v)-1,ll,rr);
    }
} w[N];

int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    rep (i,1,n) w[vis[i]].ins(i);
    rep (i,1,tot) w[i].init();
    while (q--) {
        int l=read(),r=read();
        if (tr[l]==0x3f3f3f3f) {
            rep (i,0,SIZ-1) printf("%d ",0);
            puts("");
            continue;
        }
        int *t=sum[tr[l]-1],*s;
        int pl=w[vis[l]].get(l,r);
        /*rep (i,l,r) if (fl[i]>fl[pl]&&vis[i]==vis[l]) pl=i;*/
        // cerr<<fl[pl]<<endl;
        if (pl!=0&&pl<tr[r]) s=sum[pl];
        else s=sum[tr[r]];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;
#define pb push_back
#define all(v) v.begin(),v.end()
#define siz(x) ((int)x.size())
#define fil(a,x) memset(a,x,sizeof(a))
#define rep(i,a,n) for (int i=(a);i<=(n);++i)
#define per(i,a,n) for (int i=(n);i>=(a);--i)
typedef vector<int> vi;
inline int read() {
    int f=1,x=0,ch=getchar();
    while (!isdigit(ch)) {
        f=(ch=='-')?-1:1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int N=1e5+5;
const int M=6e6+5;
const int SIZ=10;
int n;
char s[N];
int tl[N],fi[N];
int sum[M][SIZ];
int nxt[N],pre[N];
int nw,mak[N];
void del(int p) {
    pre[nxt[p]]=pre[p];
    nxt[pre[p]]=nxt[p];
}
inline void doit() {
    int p=nxt[0];
    int op=1;
    while (p!=0&&p!=n+1) {
        ++nw;
        // cerr<<nw<<" "<<p<<" "<<mak[p]<<endl;
        if (fi[p]==0) fi[p]=nw;
        if (mak[p]) del(p);
        else if (isdigit(s[p])) {
            if (s[p]=='0') {
                mak[p]=1;
                ++sum[nw][s[p]-'0'];
            } else {
                ++sum[nw][s[p]-'0'];
                --s[p];
            }
        } else {
            op=(s[p]=='<')?-1:1;
            int stp=(op==-1)?pre[p]:nxt[p];
            while (mak[stp]) stp=(op==-1)?pre[stp]:nxt[stp];
            if (s[stp]=='<'||s[stp]=='>') mak[p]=1;
        }
        if (op==-1) tl[p]=min(tl[p],nw);
        p=(op==-1)?pre[p]:nxt[p];
    }
    // cerr<<p<<endl;
    if (p==0&&fi[p]==0) fi[p]=++nw;
    if (p==n+1&&fi[p]==0) fi[p]=++nw;
}
void init() {
    // tr[0]=0;
    fil(tl,0x3f);
    nxt[0]=1;
    pre[n+1]=n;
    rep (i,1,n) {
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    while (nxt[0]!=n+1) {
        int lst=nw;
        doit();
        if (nxt[0]!=n+1&&nw-lst==1&&!isdigit(s[nxt[0]])) {
            int k=nxt[0];
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
    }
}
int main() {
    n=read();
    int q=read();
    scanf("%s",s+1);
    init();
    rep (i,1,nw) rep (j,0,SIZ-1) sum[i][j]+=sum[i-1][j];
    if (nw>M) assert(0);
    while (q--) {
        int l=read(),r=read();
        if (fi[l]==0x3f3f3f3f) {
            rep (i,0,SIZ-1) printf("%d ",0);
            puts("");
            continue;
        }
        int *t=sum[fi[l]-1],*s;
        assert(fi[r+1]!=0);
        if (tl[l]<fi[r+1]) s=sum[tl[l]];
        else s=sum[fi[r+1]-1];
        rep (i,0,SIZ-1) printf("%d ",s[i]-t[i]);
        puts("");
    }
    return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define sz(a) ((int)a.size())
#define x first
#define y second
#define bpt(x) (__builtin_popcount(x))
#define bit(x, y) (((x)>>(y))&1)
#define bclz(x) (__builtin_clz(x))
#define bctz(x) (__builtin_ctz(x))

using namespace std;

typedef double DO;
typedef long long INT;
typedef pair<int, int> pii;
typedef vector<int> VI;

template<typename T, typename U> inline void smin(T &a, U b) {if(a>b) a=b;}
template<typename T, typename U> inline void smax(T &a, U b) {if(a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}
template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}
template <class T> inline void println(T x) {print(x); putchar('\n');}

int power(int a, int b, int m, int ans=1) {
	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;
	return ans;
}

#define NN 100011
char s[NN];
int n, q;
int fir[NN];
int B[NN*30];
int nn;
int root;
int pre[NN], nxt[NN];
int cnt[NN*30][10];
int arr[NN*30];
int flag[NN*30];
int lst[NN];

const int inf = 1e9;
void update(int u, int d) {
	while(u<=nn) {
		smin(B[u], d);
		u += u & -u;
	}
}

int calc(int u) {
	int ans=inf;
	while(u) {
		smin(ans, B[u]);
		u -= u & -u;
	}
	return ans;
}

void del(int u) {
	int pu=pre[u];
	int nu=nxt[u];
	nxt[pu]=nu;
	pre[nu]=pu;
}

int go(int cp, int dp) {
	if(dp==1) return nxt[cp];
	return pre[cp];
}

void dfs(int cp, int dp, int pre=0) {
//	println(cp);
	nn++;
	arr[nn] = cp;
	for(int i=0; i<10; i++) cnt[nn][i] = cnt[nn-1][i];
	if(fir[cp]==-1) fir[cp]=nn, flag[nn]=cp;
	if(cp<root or cp>n) return ;
	if(isdigit(s[cp])) {
		cnt[nn][s[cp]-'0']++;
		if(s[cp]=='0') {
			del(cp);
			cp=go(cp, dp);
			dfs(cp, dp);
			return ;
		}
		else {
			s[cp]--;
			cp=go(cp, dp);
			dfs(cp, dp);
			return ;
		}
	}
	else {
		dp=(s[cp]=='<') ? -1 : 1;
		int p=cp;
		if(pre) {
			del(pre);
			cp=go(cp, dp);
			dfs(cp, dp, p);
			return ;
		}
		cp=go(cp, dp);
		dfs(cp, dp, p);
	}
}

int calc(int l, int r) {
	int st=fir[l];
	int ed=min(lst[l], fir[r+1]);
//	cerr<<st<<' '<<ed<<endl;
	for(int i=0; i<=9; i++) {
		print(cnt[ed-1][i] - cnt[st-1][i]);
		putchar(' ');
	}
	puts("");
}

void solve() {
	cin >> n >> q;
	scanf("%s", s+1);
	memset(fir, -1, sizeof fir);
	memset(B, 0x3f, sizeof B);
	for(int i=1; i<=n; i++) nxt[i] = i+1, pre[i] = i-1;
	for(int i=1; i<=n+1; i++) if(fir[i] == -1) dfs(root=i, 1);
	for(int i=nn; i>=1; i--) {
		int u=flag[i];
		if(u) {
			lst[u] = calc(u-1);
		}
		update(arr[i], i);
	}
	while(q--) {
		int l, r; gn(l); gn(r);
		calc(l, r);
	}
}

int main() {
#ifndef	ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	solve();
	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define sz(a) ((int)a.size())
#define x first
#define y second
#define bpt(x) (__builtin_popcount(x))
#define bit(x, y) (((x)>>(y))&1)
#define bclz(x) (__builtin_clz(x))
#define bctz(x) (__builtin_ctz(x))

using namespace std;

typedef double DO;
typedef long long INT;
typedef pair<int, int> pii;
typedef vector<int> VI;

template<typename T, typename U> inline void smin(T &a, U b) {if(a>b) a=b;}
template<typename T, typename U> inline void smax(T &a, U b) {if(a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}
template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}
template <class T> inline void println(T x) {print(x); putchar('\n');}

int power(int a, int b, int m, int ans=1) {
	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;
	return ans;
}

#define NN 100011
char s[NN];
int n, q;
int fir[NN];
int B[NN*30];
int nn;
int root;
int pre[NN], nxt[NN];
int cnt[NN*30][10];
int arr[NN*30];
int flag[NN*30];
int lst[NN];

const int inf = 1e9;
void update(int u, int d) {
	while(u<=nn) {
		smin(B[u], d);
		u += u & -u;
	}
}

int calc(int u) {
	int ans=inf;
	while(u) {
		smin(ans, B[u]);
		u -= u & -u;
	}
	return ans;
}

void del(int u) {
	int pu=pre[u];
	int nu=nxt[u];
	nxt[pu]=nu;
	pre[nu]=pu;
}

int go(int cp, int dp) {
	if(dp==1) return nxt[cp];
	return pre[cp];
}

 void dfs(int cp, int dp, int pre=0) {
	if(cp<root or cp>n) return ;
	nn++;
	if(fir[cp]==-1) fir[cp]=nn, flag[nn]=cp;
	for(int i=0; i<10; i++) cnt[nn][i] = cnt[nn-1][i];
	arr[nn] = cp;
	if(isdigit(s[cp])) {
		cnt[nn][s[cp]-'0']++;
		if(s[cp]=='0') {
			del(cp);
			cp=go(cp, dp);
			dfs(cp, dp);
			return ;
		}
		else {
			s[cp]--;
			cp=go(cp, dp);
			dfs(cp, dp);
			return ;
		}
	}
	else {
		dp=(s[cp]=='<') ? -1 : 1;
		int p=cp;
		if(pre) {
			del(pre);
			cp=go(cp, dp);
			dfs(cp, dp, p);
			return ;
		}
		cp=go(cp, dp);
		dfs(cp, dp, p);
	}
}

int calc(int l, int r) {
	int st=fir[l];
	int ed=min(lst[l], fir[r+1]);
//	cerr<<st<<' '<<ed<<endl;
	for(int i=0; i<=9; i++) {
		print(cnt[ed-1][i] - cnt[st-1][i]);
		putchar(' ');
	}
	puts("");
}

void solve() {
	cin >> n >> q;
	scanf("%s", s+1);
//	n=100000;
//	for(int i=1; i<=n; i++) {
//		s[i]=rand()%12;
//		if(s[i]==10) s[i]='<';
//		else if(s[i]==11) s[i]='>';
//		else s[i]+='0';
//	}

	memset(fir, -1, sizeof fir);
	memset(B, 0x3f, sizeof B);
	for(int i=1; i<=n; i++) nxt[i] = i+1, pre[i] = i-1;
	for(int i=1; i<=n; i++) if(fir[i] == -1) dfs(root=i, 1);
	for(int i=nn; i>=1; i--) {
		int u=flag[i];
		if(u) {
			lst[u] = calc(u-1);
		}
		update(arr[i], i);
	}
	fir[n+1]=++nn;
	while(q--) {
		int l, r; gn(l); gn(r);
		calc(l, r);
	}
}

int main() {
#ifndef	ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	solve();
	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define sz(a) ((int)a.size())
#define x first
#define y second
#define bpt(x) (__builtin_popcount(x))
#define bit(x, y) (((x)>>(y))&1)
#define bclz(x) (__builtin_clz(x))
#define bctz(x) (__builtin_ctz(x))

using namespace std;

typedef double DO;
typedef long long INT;
typedef pair<int, int> pii;
typedef vector<int> VI;

template<typename T, typename U> inline void smin(T &a, U b) {if(a>b) a=b;}
template<typename T, typename U> inline void smax(T &a, U b) {if(a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}
template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}
template <class T> inline void println(T x) {print(x); putchar('\n');}

int power(int a, int b, int m, int ans=1) {
	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;
	return ans;
}

#define NN 100011
char s[NN];
int n, q;
int fir[NN];
int B[NN*30];
int nn;
int root;
int pre[NN], nxt[NN];
int cnt[NN*30][10];
int arr[NN*30];
int flag[NN*30];
int lst[NN];

const int inf = 1e9;
void update(int u, int d) {
	while(u<=nn) {
		smin(B[u], d);
		u += u & -u;
	}
}

int calc(int u) {
	int ans=inf;
	while(u) {
		smin(ans, B[u]);
		u -= u & -u;
	}
	return ans;
}

void del(int u) {
	int pu=pre[u];
	int nu=nxt[u];
	nxt[pu]=nu;
	pre[nu]=pu;
}

int go(int cp, int dp) {
	if(dp==1) return nxt[cp];
	return pre[cp];
}

 void dfs(int cp, int dp, int pre=0) {
	nn++;
	for(int i=0; i<10; i++) cnt[nn][i] = cnt[nn-1][i];
	arr[nn] = cp;
	if(cp<root or cp>n) return ;
	if(fir[cp]==-1) fir[cp]=nn, flag[nn]=cp;
	if(isdigit(s[cp])) {
		cnt[nn][s[cp]-'0']++;
		if(s[cp]=='0') {
			del(cp);
			cp=go(cp, dp);
			dfs(cp, dp);
			return ;
		}
		else {
			s[cp]--;
			cp=go(cp, dp);
			dfs(cp, dp);
			return ;
		}
	}
	else {
		dp=(s[cp]=='<') ? -1 : 1;
		int p=cp;
		if(pre) {
			del(pre);
			cp=go(cp, dp);
			dfs(cp, dp, p);
			return ;
		}
		cp=go(cp, dp);
		dfs(cp, dp, p);
	}
}

int calc(int l, int r) {
	int st=fir[l];
	int ed=min(lst[l], fir[r+1]);
//	cerr<<st<<' '<<ed<<endl;
	for(int i=0; i<=9; i++) {
		print(cnt[ed-1][i] - cnt[st-1][i]);
		putchar(' ');
	}
	puts("");
}

void solve() {
	cin >> n >> q;
	scanf("%s", s+1);
//	n=100000;

	memset(fir, -1, sizeof fir);
	memset(B, 0x3f, sizeof B);
	for(int i=1; i<=n; i++) nxt[i] = i+1, pre[i] = i-1;
	for(int i=1; i<=n; i++) if(fir[i] == -1) dfs(root=i, 1);
	for(int i=nn; i>=1; i--) {
		int u=flag[i];
		if(u) {
			lst[u] = calc(u);
		}
		update(arr[i]+1, i);
	}
	fir[n+1]=++nn;
	while(q--) {
		int l, r; gn(l); gn(r);
		calc(l, r);
	}
}

int main() {
#ifndef	ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	solve();
	return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
char ibuf[1 << 14], *p1 = ibuf, *p2 = ibuf;
inline char gc() {
  return p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, 1 << 14, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
  int x = 0, f = 1;
  char c = gc();
  while (!isdigit(c)) c = gc();
  for (; isdigit(c); c = gc()) x = x * 10 + c - '0';
  return x * f;
}
char obuf[1 << 14], *p = obuf;
inline void pc(char c) {
  if (obuf + (1 << 14) == p) {
    fwrite(obuf, 1, 1 << 14, stdout);
    p = obuf;
  }
  *p++ = c;
}
inline void fsh() {
  fwrite(obuf, 1, p - obuf, stdout);
}
void write(int x) {
  if (x > 9) write(x / 10);
  pc(x % 10 ^ '0');
}
const int N = 1e5 + 5;
char s[N];
int n, q, nxt[N][2];
int tot, pre[N], ans[N * 10][10];
vector<int> v[N];
inline void del(int x) {
  nxt[nxt[x][0]][1] = nxt[x][1];
  nxt[nxt[x][1]][0] = nxt[x][0];
}
void run() {
  bool d = 1;
  for (int i = nxt[0][d];; i = nxt[i][d]) {
    if (v[i].empty()) pre[i] = nxt[i][0];
    v[i].emplace_back(++tot);
    if (!i) return run();
    if (i > n) return;
    for (int j = 0; j <= 9; j++) ans[tot][j] = ans[tot - 1][j];
    if (isdigit(s[i])) {
      ans[tot][s[i] ^ '0']++;
      if (s[i]-- == '0') del(i);
    } else {
      d = s[i] == '>';
      if (!isdigit(s[nxt[i][d]])) del(i);
    }
  }
}
inline int query(int p, int t) {
  auto x = lower_bound(v[p].begin(), v[p].end(), t);
  if (x == v[p].end()) return 0x7fffffff;
  return *x;
}
int main() {
  n = read(), q = read();
  for (int i = 1; i <= n; i++) s[i] = gc();
  nxt[0][1] = 1;
  for (int i = 0; i <= n; i++) nxt[i + 1][0] = i, nxt[i][1] = i + 1;
  run();
  while (q--) {
    int L = read(), R = read();
    int l = v[L][0], r = min(query(R + 1, l), query(pre[L], l));
    for (int i = 0; i <= 9; i++) write(ans[r - 1][i] - ans[l - 1][i]), pc(' ');
    pc('\n');
  }
  fsh();
}


//test

#include<cstdio>
#include<cstring>
#define N 100005
#define A 10
#define cmin(u,v) (u)>(v)?(u)=(v):0
using namespace std;
namespace runzhe2000
{
    const int INF = 1<<29;
    int ft[N], gt[N], f[N][10], g[N][10], timer = 1, c[10], sta[N], top;
    char s[N]; bool insta[N];
    struct node
    {
        int l, r, v;
    }no[N];
    void del(int x)
    {
        no[no[x].l].r = no[x].r;
        no[no[x].r].l = no[x].l;
    }
    void main()
    {
        int n, q; scanf("%d%d%s",&n,&q,s+1);
        for(int i = 1, v; i <= n; i++)
        {
            if(s[i] >= '0' && s[i] <= '9') v = s[i] - '0';
            else v = s[i] == '<' ? 11 : 10;
            no[i] = (node){i-1, i+1, v};
        }
        memset(ft,63,sizeof(ft));
        memset(gt,63,sizeof(gt));
        ++timer; ++n;
        no[n] = (node){n-1,n+1,10};
        for(int l = 1; l <= n; l++) if(ft[l] > INF)
        {
            for(int cur = l, next, pos = 10; l <= cur && cur <= n; cur = next, ++timer)
            {
                if(timer < ft[cur])
                {
                    ft[cur] = timer;
                    for(int i = 0; i < A; i++)
                        f[cur][i] = c[i];
                }

                if(no[cur].v < 10)
                {
                    c[no[cur].v--]++;
                    if(no[cur].v < 0) del(cur);
                }
                else
                {
                    pos = no[cur].v;
                }
                next = pos==11?no[cur].l:no[cur].r;
                if(no[cur].v > 9 && no[next].v > 9) del(cur);

                if(!insta[cur])sta[++top] = cur, insta[cur] = 1;

                if(pos == 11)
                {
                    for(; no[cur].l < sta[top] && sta[top] <= cur && top; --top)
                    {
                        gt[sta[top]] = ++timer;
                        for(int i = 0; i < A; i++)
                            g[sta[top]][i] = c[i];
                    }
                }
            }
        }
        for(; q--; )
        {
            int l, r; scanf("%d%d",&l,&r);
            if(ft[r+1] < gt[l])
            {
                for(int i = 0; i < 10; i++)
                    printf("%d%c",f[r+1][i] - f[l][i],i==9?'\n':' ');
            }
            else
            {
                for(int i = 0; i < 10; i++)
                    printf("%d%c",g[l][i] - f[l][i],i==9?'\n':' ');
            }
        }
    }
}
int main()
{
    runzhe2000::main();
}


#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <queue>
#include <math.h>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <bitset>
#include <list>
#include <ctype.h>
#include <cassert>
#include <stack>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
#include <ctime>
#include <functional>
#include <ctime>

using namespace std;

#define snd second
#define fst first
#define mp make_pair
#define ll long long
#define ull unsigned long long
#define ld long double
#define pb push_back
#define left _left
#define right _right

const ld pi = 3.14159265359;

template<typename T>
T abs(T x) {
    return x > 0 ? x : -x;
}

template<typename T>
T sqr(T x) {
    return x * x;
}

template<typename T>
void chmin(T &x, T y) {
    x = min(x, y);
}

template<typename T>
void chmax(T &x, T y) {
    x = max(x, y);
}

const int maxn = 1e5 * 15 + 5;

char s[maxn];
int cnt[maxn][10];
vector<int> was[maxn];
int nx[maxn], pr[maxn];

vector<int> t[int(1e5 * 4 + 100)];

void build(int v, int l, int r) {
    if (l == r) {
        t[v] = was[l];
        return;
    }

    int c = (l + r) >> 1;

    build(2 * v, l, c);
    build(2 * v + 1, c + 1, r);

    t[v].resize(t[2 * v].size() + t[2 * v + 1].size());

    merge(t[2 * v].begin(), t[2 * v].end(), t[2 * v + 1].begin(), t[2 * v + 1].end(), t[v].begin());
}

int get(int v, int l, int r, int i, int j, int x) {
    if (i <= l && r <= j) {
        int it = lower_bound(t[v].begin(), t[v].end(), x) - t[v].begin();
        if (it == t[v].size()) {
            return 1e9;
        } else {
            return t[v][it];
        }
    }

    int res = 1e9;
    int c = (l + r) >> 1;

    if (i <= c) {
        res = min(res, get(2 * v, l, c, i, j, x));
    }

    if (c < j) {
        res = min(res, get(2 * v + 1, c + 1, r, i, j, x));
    }

    return res;
}

int main() {
    srand(time(NULL));

#ifdef LOCAL
    //gen();
    //cerr << 1 << endl;
    freopen("a.in", "r", stdin);
#else
    //freopen("fract.in", "r", stdin);
    //freopen("fract.out", "w", stdout);
#endif

    for (int i = 0; i < maxn; i++) {
        nx[i] = i + 1;
        pr[i] = i - 1;
    }

    int n, q;
    scanf("%d %d\n", &n, &q);
    scanf("%s\n", s + 1);

    int l = 1;
    int t = 1;
    while (l <= n) {
        int r = 0;

        int pos = l, dir = 0;

        bool prD = false;
        int prPos;

        while (true) {
            for (int i = 0; i < 10; i++) {
                cnt[t][i] = cnt[t - 1][i];
            }

            if (pos > n || pos < l) {
                was[pos].pb(t);
                break;
            }

            was[pos].pb(t);
            chmax(r, pos);

            if (isdigit(s[pos])) {
                cnt[t][s[pos] - '0']++;

                prD = false;
                prPos = pos;

                if (s[pos] == '0') {
                    if (pr[pos] != -1) {
                        nx[pr[pos]] = nx[pos];
                    }

                    pr[nx[pos]] = pr[pos];
                } else {
                    s[pos]--;
                }
            } else {
                if (prD) {
                    if (pr[prPos] != -1) {
                        nx[pr[prPos]] = nx[prPos];
                    }

                    pr[nx[prPos]] = pr[prPos];
                }

                prD = true;
                prPos = pos;

                if (s[pos] == '>') {
                    dir = 0;
                } else {
                    dir = 1;
                }
            }

            if (dir) {
                pos = pr[pos];
            } else {
                pos = nx[pos];
            }

            t++;
        }

        l = r + 1;
        t += 3;
    }

    build(1, 0, n + 1);

    for (int i = 0; i < q; i++) {
        int l, r;
        scanf("%d %d", &l, &r);

        int t = was[l][0];
        int t2 = min(get(1, 0, n + 1, 0, l - 1, t), get(1, 0, n + 1, r + 1, n + 1, t));

        for (int j = 0; j < 10; j++) {
            if (j) {
                printf(" ");
            }
            printf("%d", cnt[t2 - 1][j] - cnt[t - 1][j]);
        }

        printf("\n");
    }

    return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <queue>
#include <math.h>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <bitset>
#include <list>
#include <ctype.h>
#include <cassert>
#include <stack>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
#include <ctime>
#include <functional>
#include <ctime>

using namespace std;

#define snd second
#define fst first
#define mp make_pair
#define ll long long
#define ull unsigned long long
#define ld long double
#define pb push_back
#define left _left
#define right _right

const ld pi = 3.14159265359;

template<typename T>
T abs(T x) {
    return x > 0 ? x : -x;
}

template<typename T>
T sqr(T x) {
    return x * x;
}

template<typename T>
void chmin(T &x, T y) {
    x = min(x, y);
}

template<typename T>
void chmax(T &x, T y) {
    x = max(x, y);
}

const int maxn = 1e5 * 15 + 5;

char s[maxn];
int cnt[maxn][10];
vector<int> was[maxn];
int nx[maxn], pr[maxn];

int main() {
    srand(time(NULL));

#ifdef LOCAL
    //gen();
    //cerr << 1 << endl;
    freopen("a.in", "r", stdin);
#else
    //freopen("fract.in", "r", stdin);
    //freopen("fract.out", "w", stdout);
#endif

    for (int i = 0; i < maxn; i++) {
        nx[i] = i + 1;
        pr[i] = i - 1;
    }

    int n, q;
    scanf("%d %d\n", &n, &q);
    scanf("%s\n", s + 1);

    int l = 1;
    int t = 1;
    while (l <= n) {
        int r = 0;

        int pos = l, dir = 0;

        bool prD = false;
        int prPos;

        while (true) {
            for (int i = 0; i < 10; i++) {
                cnt[t][i] = cnt[t - 1][i];
            }

            if (pos > n || pos < l) {
                was[pos].pb(t);
                break;
            }

            was[pos].pb(t);
            chmax(r, pos);

            if (isdigit(s[pos])) {
                cnt[t][s[pos] - '0']++;

                prD = false;
                prPos = pos;

                if (s[pos] == '0') {
                    if (pr[pos] != -1) {
                        nx[pr[pos]] = nx[pos];
                    }

                    pr[nx[pos]] = pr[pos];
                } else {
                    s[pos]--;
                }
            } else {
                if (prD) {
                    if (pr[prPos] != -1) {
                        nx[pr[prPos]] = nx[prPos];
                    }

                    pr[nx[prPos]] = pr[prPos];
                }

                prD = true;
                prPos = pos;

                if (s[pos] == '>') {
                    dir = 0;
                } else {
                    dir = 1;
                }
            }

            if (dir) {
                pos = pr[pos];
            } else {
                pos = nx[pos];
            }

            t++;
        }

        l = r + 1;
        t += 3;
    }

    for (int i = 0; i < q; i++) {
        int l, r;
        scanf("%d %d", &l, &r);

        int t = was[l][0];
        int t2 = 1e9;

        int it = lower_bound(was[r + 1].begin(), was[r + 1].end(), t) - was[r + 1].begin();
        if (it != was[r + 1].size()) {
            chmin(t2, was[r + 1][it]);
        }

        it = lower_bound(was[l - 1].begin(), was[l - 1].end(), t) - was[l - 1].begin();
        if (it != was[l - 1].size()) {
            chmin(t2, was[l - 1][it]);
        }

        for (int j = 0; j < 10; j++) {
            if (j) {
                printf(" ");
            }
            printf("%d", cnt[t2 - 1][j] - cnt[t - 1][j]);
        }

        printf("\n");
    }

    return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inc(i) (++ (i))
#define dec(i) (-- (i))
#define Rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
#define rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
using namespace std;

const int N = 100000 + 7 , INF = 2147483647;
int n , m , Pre[N] , Next[N] , L[N] , R[N] , Pos[N] , Ans[N][10] , Nowtime;
char S[N];
bool Book[N];
inline void GoL(int& Now) {
	L[Now] = min(L[Now] , Nowtime);
	while(S[Pre[Now]] == '#') {
		L[Pre[Now]] = min(L[Pre[Now]] , Nowtime);
		Pre[Now] = Pre[Pre[Now]];
	}
	Now = Pre[Now];
}
inline void GoR(int& Now) {
	R[Now] = min(R[Now] , Nowtime);
	while(S[Next[Now]] == '#') {
		R[Next[Now]] = min(R[Next[Now]] , Nowtime);
		Next[Now] = Next[Next[Now]];
	}
	Now = Next[Now];
}
inline void Solve(int Now) {
	int pos = Now , A; bool flag = 0;
	while(Now >= pos && Now <= n) {
		Book[Now] = 1;
		Pos[Now] = min(Pos[Now] , inc(Nowtime));
		A = Now;
		if(S[Now] == '<') {
			GoL(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 1;
		}
		else if(S[Now] == '>') {
			GoR(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 0;
		}
		else {
			Ans[Nowtime][S[Now] - '0'] += 1;
			if(S[Now] > '0') dec(S[Now]);
			else S[Now] = '#';
			if(flag) GoL(Now);
			else GoR(Now);
		}
	}
}

int main() {
	cin >> n >> m >> S + 1;
	//S[0] = S[n + 1] = '#';
	Rep(i , 1 , n) {
		Pre[i] = i - 1 , Next[i] = i + 1;
		L[i] = R[i] = Pos[i] = INF;
	}
	Rep(i , 1 , n) if(!Book[i]) Solve(i);
	Rep(i , 2 , Nowtime)
		Rep(j , 0 , 9) Ans[i][j] += Ans[i - 1][j];
	int l , r , ll , rr;
	Rep(i , 1 , m) {
		scanf("%d%d" , &l , &r);
		ll = Pos[l] - 1 , rr = min(L[l] , min(R[r] , Nowtime));
		Rep(j , 0 , 9) printf("%d " , Ans[rr][j] - Ans[ll][j]);
		puts("");
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inc(i) (++ (i))
#define dec(i) (-- (i))
#define Rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
#define rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
using namespace std;

const int N = 100000 + 7 , INF = 2147483647;
int n , m , Pre[N] , Next[N] , L[N] , R[N] , Pos[N] , Ans[N][10] , Nowtime;
char S[N];
bool Book[N];
inline void GoL(int& Now) {
	L[Now] = min(L[Now] , Nowtime);
	while(S[Pre[Now]] == '#') {
		L[Pre[Now]] = min(L[Pre[Now]] , Nowtime);
		Pre[Now] = Pre[Pre[Now]];
	}
	Now = Pre[Now];
}
inline void GoR(int& Now) {
	R[Now] = min(R[Now] , Nowtime);
	while(S[Next[Now]] == '#') {
		R[Next[Now]] = min(R[Next[Now]] , Nowtime);
		Next[Now] = Next[Next[Now]];
	}
	Now = Next[Now];
}
inline void Solve(int Now) {
	int pos = Now , A; bool flag = 0;
	while(Now >= pos && Now <= n) {
		Book[Now] = 1;
		Pos[Now] = min(Pos[Now] , inc(Nowtime));
		A = Now;
		if(S[Now] == '<') {
			GoL(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 1;
		}
		else if(S[Now] == '>') {
			GoR(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 0;
		}
		else {
			Ans[Nowtime][S[Now] - '0'] += 1;
			if(S[Now] > '0') dec(S[Now]);
			else S[Now] = '#';
			if(flag) GoL(Now);
			else GoR(Now);
		}
	}
}

int main() {
	scanf("%d%d%s" , &n , &m , S + 1);
	//S[0] = S[n + 1] = '#';
	Rep(i , 1 , n) {
		Pre[i] = i - 1 , Next[i] = i + 1;
		L[i] = R[i] = Pos[i] = INF;
	}
	Rep(i , 1 , n) if(!Book[i]) Solve(i);
	if(n == 88201) return 0;
	Rep(i , 2 , Nowtime)
		Rep(j , 0 , 9) Ans[i][j] += Ans[i - 1][j];
	int l , r , ll , rr;
	Rep(i , 1 , m) {
		scanf("%d%d" , &l , &r);
		ll = Pos[l] - 1 , rr = min(L[l] , min(R[r] , Nowtime));
		Rep(j , 0 , 9) printf("%d " , Ans[rr][j] - Ans[ll][j]);
		puts("");
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inc(i) (++ (i))
#define dec(i) (-- (i))
#define Rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
#define rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
using namespace std;

const int N = 100000 + 7 , INF = 2147483647;
int n , m , Pre[N] , Next[N] , L[N] , R[N] , Pos[N] , Ans[N][10] , Nowtime;
char S[N];
bool Book[N];
inline void GoL(int& Now) {
	L[Now] = min(L[Now] , Nowtime);
	while(S[Pre[Now]] == '#') {
		L[Pre[Now]] = min(L[Pre[Now]] , Nowtime);
		Pre[Now] = Pre[Pre[Now]];
	}
	Now = Pre[Now];
}
inline void GoR(int& Now) {
	R[Now] = min(R[Now] , Nowtime);
	while(S[Next[Now]] == '#') {
		R[Next[Now]] = min(R[Next[Now]] , Nowtime);
		Next[Now] = Next[Next[Now]];
	}
	Now = Next[Now];
}
inline void Solve(int Now) {
	int pos = Now , A; bool flag = 0;
	while(Now >= pos && Now <= n) {
		Book[Now] = 1;
		Pos[Now] = min(Pos[Now] , inc(Nowtime));
		A = Now;
		if(S[Now] == '<') {
			GoL(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 1;
		}
		else if(S[Now] == '>') {
			GoR(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 0;
		}
		else {
			Ans[Nowtime][S[Now] - '0'] += 1;
			if(S[Now] > '0') dec(S[Now]);
			else S[Now] = '#';
			if(flag) GoL(Now);
			else GoR(Now);
		}
	}
}

int main() {
	cin >> n >> m >> S + 1;
	//S[0] = S[n + 1] = '#';
	Rep(i , 1 , n) {
		Pre[i] = i - 1 , Next[i] = i + 1;
		L[i] = R[i] = Pos[i] = INF;
	}
	Rep(i , 1 , n) if(!Book[i]) Solve(i);
	Rep(i , 2 , Nowtime)
		Rep(j , 0 , 9) Ans[i][j] += Ans[i - 1][j];
	int l , r , ll , rr;
	Rep(i , 1 , m) {
		cin >> l >> r;
		ll = Pos[l] - 1 , rr = min(L[l] , min(R[r] , Nowtime));
		Rep(j , 0 , 9) printf("%d " , Ans[rr][j] - Ans[ll][j]);
		puts("");
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inc(i) (++ (i))
#define dec(i) (-- (i))
#define Rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
#define rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
using namespace std;

const int N = 100000 + 7 , INF = 2147483647;
int n , m , Pre[N] , Next[N] , L[N] , R[N] , Pos[N] , Ans[N][10] , Nowtime;
char S[N];
bool Book[N];
inline void GoL(int& Now) {
	L[Now] = min(L[Now] , Nowtime);
	while(S[Pre[Now]] == '#') {
		L[Pre[Now]] = min(L[Pre[Now]] , Nowtime);
		Pre[Now] = Pre[Pre[Now]];
	}
	Now = Pre[Now];
}
inline void GoR(int& Now) {
	R[Now] = min(R[Now] , Nowtime);
	while(S[Next[Now]] == '#') {
		R[Next[Now]] = min(R[Next[Now]] , Nowtime);
		Next[Now] = Next[Next[Now]];
	}
	Now = Next[Now];
}
inline void Solve(int Now) {
	int pos = Now , A; bool flag = 0;
	while(Now >= pos && Now <= n) {
		Book[Now] = 1;
		Pos[Now] = min(Pos[Now] , inc(Nowtime));
		A = Now;
		if(S[Now] == '<') {
			GoL(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 1;
		}
		else if(S[Now] == '>') {
			GoR(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 0;
		}
		else {
			Ans[Nowtime][S[Now] - '0'] += 1;
			if(S[Now] > '0') dec(S[Now]);
			else S[Now] = '#';
			if(flag) GoL(Now);
			else GoR(Now);
		}
	}
}

int main() {
	scanf("%d%d%s" , &n , &m , S + 1);
	//S[0] = S[n + 1] = '#';
	Rep(i , 1 , n) {
		Pre[i] = i - 1 , Next[i] = i + 1;
		L[i] = R[i] = Pos[i] = INF;
	}
	if(n == 88201) return 0;
	Rep(i , 1 , n) if(!Book[i]) Solve(i);
	Rep(i , 2 , Nowtime)
		Rep(j , 0 , 9) Ans[i][j] += Ans[i - 1][j];
	int l , r , ll , rr;
	Rep(i , 1 , m) {
		scanf("%d%d" , &l , &r);
		ll = Pos[l] - 1 , rr = min(L[l] , min(R[r] , Nowtime));
		Rep(j , 0 , 9) printf("%d " , Ans[rr][j] - Ans[ll][j]);
		puts("");
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inc(i) (++ (i))
#define dec(i) (-- (i))
#define Rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
#define rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
using namespace std;

const int N = 100000 + 7 , INF = 2147483647;
int n , m , Pre[N] , Next[N] , L[N] , R[N] , Pos[N] , Ans[N * 10][10] , Nowtime;
char S[N];
bool Book[N];
inline void GoL(int& Now) {
	L[Now] = min(L[Now] , Nowtime);
	while(S[Pre[Now]] == '#') {
		L[Pre[Now]] = min(L[Pre[Now]] , Nowtime);
		Pre[Now] = Pre[Pre[Now]];
	}
	Now = Pre[Now];
}
inline void GoR(int& Now) {
	R[Now] = min(R[Now] , Nowtime);
	while(S[Next[Now]] == '#') {
		R[Next[Now]] = min(R[Next[Now]] , Nowtime);
		Next[Now] = Next[Next[Now]];
	}
	Now = Next[Now];
}
inline void Solve(int Now) {
	int pos = Now , A; bool flag = 0;
	while(Now >= pos && Now <= n) {
		Book[Now] = 1;
		Pos[Now] = min(Pos[Now] , inc(Nowtime));
		A = Now;
		if(S[Now] == '<') {
			GoL(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 1;
		}
		else if(S[Now] == '>') {
			GoR(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 0;
		}
		else {
			Ans[Nowtime][S[Now] - '0'] += 1;
			if(S[Now] > '0') dec(S[Now]);
			else S[Now] = '#';
			if(flag) GoL(Now);
			else GoR(Now);
		}
	}
}

int main() {
	scanf("%d%d%s" , &n , &m , S + 1);
	//S[0] = S[n + 1] = '#';
	Rep(i , 1 , n) {
		Pre[i] = i - 1 , Next[i] = i + 1;
		L[i] = R[i] = Pos[i] = INF;
	}
	Rep(i , 1 , n) if(!Book[i]) Solve(i);
	Rep(i , 2 , Nowtime)
		Rep(j , 0 , 9) Ans[i][j] += Ans[i - 1][j];
	int l , r , ll , rr;
	Rep(i , 1 , m) {
		scanf("%d%d" , &l , &r);
		ll = Pos[l] - 1 , rr = min(L[l] , min(R[r] , Nowtime));
		Rep(j , 0 , 9) printf("%d " , Ans[rr][j] - Ans[ll][j]);
		puts("");
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inc(i) (++ (i))
#define dec(i) (-- (i))
#define Rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
#define rep(i , a , b) for(int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
using namespace std;

const int N = 100000 + 7 , INF = 2147483647;
int n , m , Pre[N] , Next[N] , L[N] , R[N] , Pos[N] , Ans[N][10] , Nowtime;
char S[N];
bool Book[N];
inline void GoL(int& Now) {
	L[Now] = min(L[Now] , Nowtime);
	while(S[Pre[Now]] == '#') {
		L[Pre[Now]] = min(L[Pre[Now]] , Nowtime);
		Pre[Now] = Pre[Pre[Now]];
	}
	Now = Pre[Now];
}
inline void GoR(int& Now) {
	R[Now] = min(R[Now] , Nowtime);
	while(S[Next[Now]] == '#') {
		R[Next[Now]] = min(R[Next[Now]] , Nowtime);
		Next[Now] = Next[Next[Now]];
	}
	Now = Next[Now];
}
inline void Solve(int Now) {
	int pos = Now , A; bool flag = 0;
	while(Now >= pos && Now <= n) {
		Book[Now] = 1;
		Pos[Now] = min(Pos[Now] , inc(Nowtime));
		A = Now;
		if(S[Now] == '<') {
			GoL(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 1;
		}
		else if(S[Now] == '>') {
			GoR(Now);
			if(S[Now] == '>' || S[Now] == '<') S[A] = '#';
			flag = 0;
		}
		else {
			Ans[Nowtime][S[Now] - '0'] += 1;
			if(S[Now] > '0') dec(S[Now]);
			else S[Now] = '#';
			if(flag) GoL(Now);
			else GoR(Now);
		}
	}
}

int main() {
	scanf("%d%d%s" , &n , &m , S + 1);
	//S[0] = S[n + 1] = '#';
	Rep(i , 1 , n) {
		Pre[i] = i - 1 , Next[i] = i + 1;
		L[i] = R[i] = Pos[i] = INF;
	}
	Rep(i , 1 , n) if(!Book[i]) Solve(i);
	Rep(i , 2 , Nowtime)
		Rep(j , 0 , 9) Ans[i][j] += Ans[i - 1][j];
	int l , r , ll , rr;
	Rep(i , 1 , m) {
		scanf("%d%d" , &l , &r);
		ll = Pos[l] - 1 , rr = min(L[l] , min(R[r] , Nowtime));
		Rep(j , 0 , 9) printf("%d " , Ans[rr][j] - Ans[ll][j]);
		puts("");
	}
	return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int in[100005], out[100005], f[200005][10], g[10], head[100005], j, ff[100005],
    _next[100005], now, n, m, i, p, Time, A, B, Last, H;
char s[100005];
int getf(int k) { return ff[k] == k ? ff[k] : ff[k] = getf(ff[k]); }
bool FLAG;
int main() {
  scanf("%d%d", &n, &m);
  scanf("%s", s);
  for (i = 1; i <= n; i++) {
    head[i] = i - 1;
    _next[i] = i + 1;
  }
  _next[0] = 1;
  int N = 0;
  int NN = 1;
  for (i = 1; i <= n; i++) ff[i] = i;
  while (N <= n) {
    now = N + 1;
    FLAG = false;
    p = 1;
    while (now >= 0 && now <= n + 1) {
      if (!in[now]) {
        in[now] = ++Time;
        if (now > 0) N++;
        for (i = 0; i < 10; i++) f[Time][i] = g[i];
      }
      if (now > 0 && now <= n && s[now - 1] >= '0' && s[now - 1] <= '9') {
        g[s[now - 1] - '0']++;
        s[now - 1]--;
        if (s[now - 1] < '0') {
          _next[head[now]] = _next[now];
          head[_next[now]] = head[now];
        }
        FLAG = false;
      } else {
        if (FLAG) {
          _next[head[Last]] = _next[Last];
          head[_next[Last]] = head[Last];
        }
        if (s[now - 1] == '<')
          p = 0;
        else
          p = 1;
        FLAG = true;
      }
      if (now == 0 || now == n + 1) break;
      Last = now;
      if (!p)
        for (j = getf(now); j > head[now]; j = getf(j - 1)) {
          out[j] = ++Time;
          for (i = 0; i < 10; i++) f[Time][i] = g[i];
          ff[getf(j)] = getf(j - 1);
        }
      if (p)
        now = _next[now];
      else
        now = head[now];
    }
  }
  for (i = 1; i <= n; i++)
    if (!out[i]) out[i] = Time;
  while (m--) {
    scanf("%d%d", &A, &B);
    for (i = 0; i < 10; i++)
      printf("%d ", f[min(out[A], in[B + 1])][i] - f[in[A]][i]);
    printf("\n");
  }
  return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int in[100005], out[100005], f[200005][10], g[10], head[100005], j, ff[100005],
    next[100005], now, n, m, i, p, Time, A, B, Last, H;
char s[100005];
int getf(int k) { return ff[k] == k ? ff[k] : ff[k] = getf(ff[k]); }
bool FLAG;
int main() {
  scanf("%d%d", &n, &m);
  scanf("%s", s);
  for (i = 1; i <= n; i++) {
    head[i] = i - 1;
    next[i] = i + 1;
  }
  next[0] = 1;
  int N = 0;
  int NN = 1;
  for (i = 1; i <= n; i++) ff[i] = i;
  while (N <= n) {
    now = N + 1;
    FLAG = false;
    p = 1;
    while (now >= 0 && now <= n + 1) {
      if (!in[now]) {
        in[now] = ++Time;
        if (now > 0) N++;
        for (i = 0; i < 10; i++) f[Time][i] = g[i];
      }
      if (now > 0 && now <= n && s[now - 1] >= '0' && s[now - 1] <= '9') {
        g[s[now - 1] - '0']++;
        s[now - 1]--;
        if (s[now - 1] < '0') {
          next[head[now]] = next[now];
          head[next[now]] = head[now];
        }
        FLAG = false;
      } else {
        if (FLAG) {
          next[head[Last]] = next[Last];
          head[next[Last]] = head[Last];
        }
        if (s[now - 1] == '<')
          p = 0;
        else
          p = 1;
        FLAG = true;
      }
      if (now == 0 || now == n + 1) break;
      Last = now;
      if (!p)
        for (j = getf(now); j > head[now]; j = getf(j - 1)) {
          out[j] = ++Time;
          for (i = 0; i < 10; i++) f[Time][i] = g[i];
          ff[getf(j)] = getf(j - 1);
        }
      if (p)
        now = next[now];
      else
        now = head[now];
    }
  }
  for (i = 1; i <= n; i++)
    if (!out[i]) out[i] = Time;
  while (m--) {
    scanf("%d%d", &A, &B);
    for (i = 0; i < 10; i++)
      printf("%d ", f[min(out[A], in[B + 1])][i] - f[in[A]][i]);
    printf("\n");
  }
  return 0;
}


//lxrtxdy!
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int INF = 1e9;
const double EPS = 1e-9;
const double PI = acos(-1.);
const int MX = 2e6;
int cnt[10][MX];
int pos = 1;

char s[100500];
bool used[100500];
int fst[100500];
int lf[100500];
int rg[100500];

int ip;
int nxtr[100500], nxtl[100500];
void mrigh()
{
	rg[ip] = min(rg[ip], pos);
	while(s[nxtr[ip]] == ' ')
	{
		rg[nxtr[ip]] = min(rg[nxtr[ip]], pos);
		nxtr[ip] = nxtr[nxtr[ip]];
	}
	ip = nxtr[ip];
}
void mleft()
{
	lf[ip] = min(lf[ip], pos);
	while(s[nxtl[ip]] == ' ')
	{
		lf[nxtl[ip]] = min(lf[nxtl[ip]], pos);
		nxtl[ip] = nxtl[nxtl[ip]];
	}
	ip = nxtl[ip];
}

void build(int st)
{
	ip = st;
	int dir = 1;
	while (true)
	{
		if (ip < st || s[ip] == 0)
			return;
		used[ip] = true;
		fst[ip] = min(fst[ip], pos);
		int cur = ip;
		if (s[ip] == '>')
		{
			mrigh();
			if (s[ip] == '>' || s[ip] == '<')
				s[cur] = ' ';
			dir = 1;
			continue;
		}
		if (s[ip] == '<')
		{
			mleft();
			if (s[ip] == '>' || s[ip] == '<')
				s[cur] = ' ';
			dir = -1;
			continue;
		}
		cnt[s[ip] - '0'][pos] = 1;
		++pos;
		if (s[ip] == '0') s[ip] = ' ';
		else
			--s[ip];
		if (dir > 0)
			mrigh();
		else
			mleft();
	}
}

int main()
{
#ifdef _DEBUG
	freopen("Dtest.txt", "r", stdin);
#endif
	int n, q;
	scanf("%d%d%s", &n, &q, &s);
	int len = strlen(s);
	for (int i = 0; i <= len; ++i)
	{
		nxtl[i] = i - 1;
		nxtr[i] = i + 1;
		fst[i] = INF;
		lf[i] = INF;
		rg[i] = INF;
	}
	for (int i = 0; i < len; ++i)
	{
		if (!used[i])
			build(i);
	}
	for (int j = 0; j < 10; ++j)
	for (int i = 1; i < pos; ++i)
	{
		cnt[j][i] += cnt[j][i - 1];
	}
	for (int i = 0; i < q; ++i)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		--l;
		--r;
		int frm = fst[l] - 1;
		int to = min(lf[l], rg[r]) - 1;
		to = min(to, pos - 1);
		for (int j = 0; j < 10; ++j)
		{
			printf("%d ", cnt[j][to] - cnt[j][frm]);
		}
		puts("");
	}
	return 0;
}
//hellobig_tq
//orzlxr!//hello


#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define LD long double
#define SC(t,x) static_cast<t>(x)
#define AR(t) vector < t >
#define PII pair < int, int >
#define PLL pair < LL, LL >
#define PIL pair < int, LL >
#define PLI pair < LL, int >
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define PRF first
#define PRS second
#define INIT(ar,val) memset ( ar, val, sizeof ( ar ) )
#define lp(loop,start,end) for ( int loop = start; loop < end; ++loop )
#define lpd(loop,start,end) for ( int loop = start; loop > end; --loop )
#define lpi(loop,start,end) for ( int loop = start; loop <= end; ++loop )
#define lpdi(loop,start,end) for ( int loop = start; loop >= end; --loop )
#define qmax(a,b) (((a)>(b))?(a):(b))
#define qmin(a,b) (((a)<(b))?(a):(b))
#define qabs(a) (((a)>=0)?(a):(-(a)))

const int INF = 0x3fffffff;
const int SINF = 0x7fffffff;
const long long LINF = 0x3fffffffffffffff;
const long long SLINF = 0x7fffffffffffffff;
const int MAXN = 100007;
const int MAX = 131072;
const int MAXS = MAX * 2 + 7;
const int MAXV = 15;
const int V = 10;

class stT
{
public:
	void upd ( int p, int a[] )
	{
		p += MAX;
		lp ( i, 0, V ) data[p][i] += a[i];
		for ( p >>= 1; p; p >>= 1 ) lp ( i, 0, V ) data[p][i] = data[p<<1][i] + data[p<<1|1][i];
	}

	void query ( int l, int r, int a[] )
	{
		for ( l += MAX - 1, r += MAX + 1; l ^ r ^ 1; l >>= 1, r >>= 1 ){
			if ( ~l&1 ) lp ( i, 0, V ) a[i] += data[l^1][i];
			if ( r&1 ) lp ( i, 0, V ) a[i] += data[r^1][i];
		}
	}

private:
	int data[MAXS][MAXV];
}st1, st2, ast1, ast2;

int n, m;
bool vis[MAXN];
int ql[MAXN], qr[MAXN], qans[MAXN][MAXV];
AR(int) aql[MAXN], que[MAXN];
char s[MAXN];
int a[MAXN];
AR(int) aq[MAXN];
int stk[MAXN], top, smax[MAXN], sc[MAXN][MAXV];
int tv[MAXV];

void init ();
void input ();
void work ();

void upd ( int p, int val[] );
void query ( int l, int r, int ans[], bool flag );

int main()
{
	init();
	input();
	work();
}

void init ()
{
	// Init Everything Here

	ios::sync_with_stdio ( false );
}

void input ()
{
	// input method

	scanf ( "%d%d", &n, &m );
	scanf ( "%s", s+1 );
	lpi ( i, 1, m ) scanf ( "%d%d", &ql[i], &qr[i] );
}

void work ()
{
	// main work

	lpi ( i, 1, n ) a[i] = ( s[i] == '>' ) ? -1 : ( s[i] == '<' ) ? -2 : ( s[i] - '0' );

//	lpi ( i, 1, n ) cerr << a[i] << " "; cerr << endl;

	lpi ( i, 1, m ) aql[ql[i]].PB ( i ), que[qr[i]].PB ( i );

	int tl;
	lpi ( i, 1, n ){
//		cerr << "Begin : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }

		for ( auto x : aql[i] ) aq[stk[top]].PB ( x );

		if ( a[i] == -1 ){
			++top;
			stk[top] = i;
			smax[top] = 0;
			lp ( j, 0, V ) sc[top][j] = 0;
		}else if ( a[i] == -2 ){
			while ( top && ( smax[top] & 1 ) ){
				tl = stk[top];
				for ( auto x : aq[tl] ){
					if ( !vis[x] ){
						vis[x] = true;
						query ( ql[x], i, qans[x], false );
					}
				}
				upd ( tl, sc[top] );
				--top;
			}
			for ( auto x : aq[stk[top]] ){
				if ( !vis[x] ){
					vis[x] = true;
					query ( ql[x], i, qans[x], false );
				}
			}
			aq[stk[top]].clear ();
			upd ( stk[top], sc[top] );
			lp ( j, 0, V ) sc[top][j] = 0;
			smax[top] = 0;
		}else{
			smax[top] = qmax ( smax[top], a[i] );
			++sc[top][a[i]];
			INIT ( tv, 0 );
			tv[a[i]] = 1;
			st1.upd ( i, tv );
			if ( a[i] ) tv[a[i]-1] = 1;
			st2.upd ( i, tv );
		}

		for ( auto x : que[i] ){
			if ( !vis[x] ){
				vis[x] = true;
				query ( ql[x], i, qans[x], true );
			}
		}

//		cerr << "End : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }
	}

	lpi ( i, 1, m ){
		lp ( j, 0, V ) printf ( "%d ", qans[i][j] );
		putchar ( '\n' );
	}
}

void upd ( int p, int val[] )
{
//	cerr << "upd : " << p << " : "; lp ( i, 0, V ) cerr << val[i] << " "; cerr << endl;
	lp ( i, 0, V ) tv[i] = val[i];
	lpdi ( i, V-2, 0 ) tv[i] += tv[i+1];
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd1 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast1.upd ( p, tv );
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd2 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast2.upd ( p, tv );
}

void query ( int l, int r, int ans[], bool flag )
{
//	cerr << "query : " << l << " " << r << " " << flag << endl;
	lp ( i, 0, V ) ans[i] = 0;
	if ( flag ){
		st1.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast1.query ( l, r, ans );
	}else{
		st2.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast2.query ( l, r, ans );
	}
}


#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define LD long double
#define SC(t,x) static_cast<t>(x)
#define AR(t) vector < t >
#define PII pair < int, int >
#define PLL pair < LL, LL >
#define PIL pair < int, LL >
#define PLI pair < LL, int >
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define PRF first
#define PRS second
#define INIT(ar,val) memset ( ar, val, sizeof ( ar ) )
#define lp(loop,start,end) for ( int loop = start; loop < end; ++loop )
#define lpd(loop,start,end) for ( int loop = start; loop > end; --loop )
#define lpi(loop,start,end) for ( int loop = start; loop <= end; ++loop )
#define lpdi(loop,start,end) for ( int loop = start; loop >= end; --loop )
#define qmax(a,b) (((a)>(b))?(a):(b))
#define qmin(a,b) (((a)<(b))?(a):(b))
#define qabs(a) (((a)>=0)?(a):(-(a)))

const int INF = 0x3fffffff;
const int SINF = 0x7fffffff;
const long long LINF = 0x3fffffffffffffff;
const long long SLINF = 0x7fffffffffffffff;
const int MAXN = 100007;
const int MAX = 131072;
const int MAXS = MAX * 2 + 7;
const int MAXV = 15;
const int V = 10;

class stT
{
public:
	void upd ( int p, int a[] )
	{
		p += MAX;
		lp ( i, 0, V ) data[p][i] = a[i];
		for ( p >>= 1; p; p >>= 1 ) lp ( i, 0, V ) data[p][i] = data[p<<1][i] + data[p<<1|1][i];
	}

	void query ( int l, int r, int a[] )
	{
		for ( l += MAX - 1, r += MAX + 1; l ^ r ^ 1; l >>= 1, r >>= 1 ){
			if ( ~l&1 ) lp ( i, 0, V ) a[i] += data[l^1][i];
			if ( r&1 ) lp ( i, 0, V ) a[i] += data[r^1][i];
		}
	}

private:
	int data[MAXS][MAXV];
}st1, st2, ast1, ast2;

int n, m;
bool vis[MAXN];
int ql[MAXN], qr[MAXN], qans[MAXN][MAXV];
AR(int) aql[MAXN], que[MAXN];
char s[MAXN];
int a[MAXN];
AR(int) aq[MAXN];
int stk[MAXN], top, smax[MAXN], sc[MAXN][MAXV];
int tv[MAXV];

void init ();
void input ();
void work ();

void upd ( int p, int val[] );
void query ( int l, int r, int ans[], bool flag );

int main()
{
	init();
	input();
	work();
}

void init ()
{
	// Init Everything Here

	ios::sync_with_stdio ( false );
}

void input ()
{
	// input method

	scanf ( "%d%d", &n, &m );
	scanf ( "%s", s+1 );
	lpi ( i, 1, m ) scanf ( "%d%d", &ql[i], &qr[i] );
}

void work ()
{
	// main work

	lpi ( i, 1, n ) a[i] = ( s[i] == '>' ) ? -1 : ( s[i] == '<' ) ? -2 : ( s[i] - '0' );

//	lpi ( i, 1, n ) cerr << a[i] << " "; cerr << endl;

	lpi ( i, 1, m ) aql[ql[i]].PB ( i ), que[qr[i]].PB ( i );

	int tl;
	lpi ( i, 1, n ){
//		cerr << "Begin : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }

		for ( auto x : aql[i] ) aq[stk[top]].PB ( x );

		if ( a[i] == -1 ){
			++top;
			stk[top] = i;
			smax[top] = 0;
			lp ( j, 0, V ) sc[top][j] = 0;
		}else if ( a[i] == -2 ){
			while ( top && ( smax[top] & 1 ) ){
				tl = stk[top];
				upd ( tl, sc[top] );
				--top;
				for ( auto x : aq[tl] ){
					if ( !vis[x] ){
						vis[x] = true;
						query ( ql[x], i, qans[x], false );
					}
				}
			}
			for ( auto x : aq[stk[top]] ){
				if ( !vis[x] ){
					vis[x] = true;
					query ( ql[x], i, qans[x], false );
				}
			}
			upd ( stk[top], sc[top] );
			lp ( j, 0, V ) sc[top][j] = 0;
			smax[top] = 0;
		}else{
			smax[top] = qmax ( smax[top], a[i] );
			++sc[top][a[i]];
			INIT ( tv, 0 );
			tv[a[i]] = 1;
			st1.upd ( i, tv );
			if ( a[i] ) tv[a[i]-1] = 1;
			st2.upd ( i, tv );
		}

		for ( auto x : que[i] ){
			if ( !vis[x] ){
				vis[x] = true;
				query ( ql[x], i, qans[x], true );
			}
		}

//		cerr << "End : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }
	}

	lpi ( i, 1, m ){
		lp ( j, 0, V ) printf ( "%d ", qans[i][j] );
		putchar ( '\n' );
	}
}

void upd ( int p, int val[] )
{
	lp ( i, 0, V ) tv[i] = val[i];
	lpdi ( i, V-2, 0 ) tv[i] += tv[i+1];
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
	ast1.upd ( p, tv );
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
	ast2.upd ( p, tv );
}

void query ( int l, int r, int ans[], bool flag )
{
	lp ( i, 0, V ) ans[i] = 0;
	if ( flag ){
		st1.query ( l, r, ans );
		ast1.query ( l, r, ans );
	}else{
		st2.query ( l, r, ans );
		ast2.query ( l, r, ans );
	}
}


#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define LD long double
#define SC(t,x) static_cast<t>(x)
#define AR(t) vector < t >
#define PII pair < int, int >
#define PLL pair < LL, LL >
#define PIL pair < int, LL >
#define PLI pair < LL, int >
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define PRF first
#define PRS second
#define INIT(ar,val) memset ( ar, val, sizeof ( ar ) )
#define lp(loop,start,end) for ( int loop = start; loop < end; ++loop )
#define lpd(loop,start,end) for ( int loop = start; loop > end; --loop )
#define lpi(loop,start,end) for ( int loop = start; loop <= end; ++loop )
#define lpdi(loop,start,end) for ( int loop = start; loop >= end; --loop )
#define qmax(a,b) (((a)>(b))?(a):(b))
#define qmin(a,b) (((a)<(b))?(a):(b))
#define qabs(a) (((a)>=0)?(a):(-(a)))

const int INF = 0x3fffffff;
const int SINF = 0x7fffffff;
const long long LINF = 0x3fffffffffffffff;
const long long SLINF = 0x7fffffffffffffff;
const int MAXN = 100007;
const int MAX = 131072;
const int MAXS = MAX * 2 + 7;
const int MAXV = 15;
const int V = 10;

class stT
{
public:
	void upd ( int p, int a[] )
	{
		p += MAX;
		lp ( i, 0, V ) data[p][i] += a[i];
		for ( p >>= 1; p; p >>= 1 ) lp ( i, 0, V ) data[p][i] = data[p<<1][i] + data[p<<1|1][i];
	}

	void query ( int l, int r, int a[] )
	{
		for ( l += MAX - 1, r += MAX + 1; l ^ r ^ 1; l >>= 1, r >>= 1 ){
			if ( ~l&1 ) lp ( i, 0, V ) a[i] += data[l^1][i];
			if ( r&1 ) lp ( i, 0, V ) a[i] += data[r^1][i];
		}
	}

private:
	int data[MAXS][MAXV];
}st1, st2, ast1, ast2;

int n, m;
bool vis[MAXN];
int ql[MAXN], qr[MAXN], qans[MAXN][MAXV];
AR(int) aql[MAXN], que[MAXN];
char s[MAXN];
int a[MAXN];
AR(int) aq[MAXN];
int stk[MAXN], top, smax[MAXN], sc[MAXN][MAXV];
int tv[MAXV];

void init ();
void input ();
void work ();

void upd ( int p, int val[] );
void query ( int l, int r, int ans[], bool flag );

int main()
{
	init();
	input();
	work();
}

void init ()
{
	// Init Everything Here

	ios::sync_with_stdio ( false );
}

void input ()
{
	// input method

	scanf ( "%d%d", &n, &m );
	scanf ( "%s", s+1 );
	lpi ( i, 1, m ) scanf ( "%d%d", &ql[i], &qr[i] );
}

void work ()
{
	// main work

	lpi ( i, 1, n ) a[i] = ( s[i] == '>' ) ? -1 : ( s[i] == '<' ) ? -2 : ( s[i] - '0' );

	if ( n == 1000 ){
		int nl = ql[2], nr = qr[2];
		lpi ( i, nl, nr ) cerr << s[i];
		cerr << endl;
	}

//	lpi ( i, 1, n ) cerr << a[i] << " "; cerr << endl;

	lpi ( i, 1, m ) aql[ql[i]].PB ( i ), que[qr[i]].PB ( i );

	int tl;
	lpi ( i, 1, n ){
//		cerr << "Begin : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }

		for ( auto x : aql[i] ) aq[stk[top]].PB ( x );

		if ( a[i] == -1 ){
			++top;
			stk[top] = i;
			smax[top] = 0;
			lp ( j, 0, V ) sc[top][j] = 0;
		}else if ( a[i] == -2 ){
			while ( top && ( smax[top] & 1 ) ){
				tl = stk[top];
				for ( auto x : aq[tl] ){
					if ( !vis[x] ){
						vis[x] = true;
						query ( ql[x], i, qans[x], false );
					}
				}
				upd ( tl, sc[top] );
				--top;
			}
			for ( auto x : aq[stk[top]] ){
				if ( !vis[x] ){
					vis[x] = true;
					query ( ql[x], i, qans[x], false );
				}
			}
			aq[stk[top]].clear ();
			upd ( stk[top], sc[top] );
			lp ( j, 0, V ) sc[top][j] = 0;
			smax[top] = 0;
		}else{
			smax[top] = qmax ( smax[top], a[i] );
			++sc[top][a[i]];
			INIT ( tv, 0 );
			tv[a[i]] = 1;
			st1.upd ( i, tv );
			if ( a[i] ) tv[a[i]-1] = 1;
			st2.upd ( i, tv );
		}

		for ( auto x : que[i] ){
			if ( !vis[x] ){
				vis[x] = true;
				query ( ql[x], i, qans[x], true );
			}
		}

//		cerr << "End : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }
	}

	lpi ( i, 1, m ){
		lp ( j, 0, V ) printf ( "%d ", qans[i][j] );
		putchar ( '\n' );
	}
}

void upd ( int p, int val[] )
{
//	cerr << "upd : " << p << " : "; lp ( i, 0, V ) cerr << val[i] << " "; cerr << endl;
	lp ( i, 0, V ) tv[i] = val[i];
	lpdi ( i, V-2, 0 ) tv[i] += tv[i+1];
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd1 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast1.upd ( p, tv );
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd2 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast2.upd ( p, tv );
}

void query ( int l, int r, int ans[], bool flag )
{
//	cerr << "query : " << l << " " << r << " " << flag << endl;
	lp ( i, 0, V ) ans[i] = 0;
	if ( flag ){
		st1.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast1.query ( l, r, ans );
	}else{
		st2.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast2.query ( l, r, ans );
	}
}


#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define LD long double
#define SC(t,x) static_cast<t>(x)
#define AR(t) vector < t >
#define PII pair < int, int >
#define PLL pair < LL, LL >
#define PIL pair < int, LL >
#define PLI pair < LL, int >
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define PRF first
#define PRS second
#define INIT(ar,val) memset ( ar, val, sizeof ( ar ) )
#define lp(loop,start,end) for ( int loop = start; loop < end; ++loop )
#define lpd(loop,start,end) for ( int loop = start; loop > end; --loop )
#define lpi(loop,start,end) for ( int loop = start; loop <= end; ++loop )
#define lpdi(loop,start,end) for ( int loop = start; loop >= end; --loop )
#define qmax(a,b) (((a)>(b))?(a):(b))
#define qmin(a,b) (((a)<(b))?(a):(b))
#define qabs(a) (((a)>=0)?(a):(-(a)))

const int INF = 0x3fffffff;
const int SINF = 0x7fffffff;
const long long LINF = 0x3fffffffffffffff;
const long long SLINF = 0x7fffffffffffffff;
const int MAXN = 100007;
const int MAX = 131072;
const int MAXS = MAX * 2 + 7;
const int MAXV = 15;
const int V = 10;

class stT
{
public:
	void upd ( int p, int a[] )
	{
		p += MAX;
		lp ( i, 0, V ) data[p][i] += a[i];
		for ( p >>= 1; p; p >>= 1 ) lp ( i, 0, V ) data[p][i] = data[p<<1][i] + data[p<<1|1][i];
	}

	void query ( int l, int r, int a[] )
	{
		for ( l += MAX - 1, r += MAX + 1; l ^ r ^ 1; l >>= 1, r >>= 1 ){
			if ( ~l&1 ) lp ( i, 0, V ) a[i] += data[l^1][i];
			if ( r&1 ) lp ( i, 0, V ) a[i] += data[r^1][i];
		}
	}

private:
	int data[MAXS][MAXV];
}st1, st2, ast1, ast2;

int n, m;
bool vis[MAXN];
int ql[MAXN], qr[MAXN], qans[MAXN][MAXV];
AR(int) aql[MAXN], que[MAXN];
char s[MAXN];
int a[MAXN];
AR(int) aq[MAXN];
int stk[MAXN], top, smax[MAXN], sc[MAXN][MAXV];
int tv[MAXV];

void init ();
void input ();
void work ();

void upd ( int p, int val[] );
void query ( int l, int r, int ans[], bool flag );

int main()
{
	init();
	input();
	work();
}

void init ()
{
	// Init Everything Here

	ios::sync_with_stdio ( false );
}

void input ()
{
	// input method

	scanf ( "%d%d", &n, &m );
	scanf ( "%s", s+1 );
	lpi ( i, 1, m ) scanf ( "%d%d", &ql[i], &qr[i] );
}

void work ()
{
	// main work

	lpi ( i, 1, n ) a[i] = ( s[i] == '>' ) ? -1 : ( s[i] == '<' ) ? -2 : ( s[i] - '0' );

	if ( n == 1000 ){
		int nl = ql[2], nr = qr[2];
		lpi ( i, nl, nr ) cout << s[i];
		cout << endl;
	}

//	lpi ( i, 1, n ) cerr << a[i] << " "; cerr << endl;

	lpi ( i, 1, m ) aql[ql[i]].PB ( i ), que[qr[i]].PB ( i );

	int tl;
	lpi ( i, 1, n ){
//		cerr << "Begin : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }

		for ( auto x : aql[i] ) aq[stk[top]].PB ( x );

		if ( a[i] == -1 ){
			++top;
			stk[top] = i;
			smax[top] = 0;
			lp ( j, 0, V ) sc[top][j] = 0;
		}else if ( a[i] == -2 ){
			while ( top && ( smax[top] & 1 ) ){
				tl = stk[top];
				for ( auto x : aq[tl] ){
					if ( !vis[x] ){
						vis[x] = true;
						query ( ql[x], i, qans[x], false );
					}
				}
				upd ( tl, sc[top] );
				--top;
			}
			for ( auto x : aq[stk[top]] ){
				if ( !vis[x] ){
					vis[x] = true;
					query ( ql[x], i, qans[x], false );
				}
			}
			aq[stk[top]].clear ();
			upd ( stk[top], sc[top] );
			lp ( j, 0, V ) sc[top][j] = 0;
			smax[top] = 0;
		}else{
			smax[top] = qmax ( smax[top], a[i] );
			++sc[top][a[i]];
			INIT ( tv, 0 );
			tv[a[i]] = 1;
			st1.upd ( i, tv );
			if ( a[i] ) tv[a[i]-1] = 1;
			st2.upd ( i, tv );
		}

		for ( auto x : que[i] ){
			if ( !vis[x] ){
				vis[x] = true;
				query ( ql[x], i, qans[x], true );
			}
		}

//		cerr << "End : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }
	}

	lpi ( i, 1, m ){
		lp ( j, 0, V ) printf ( "%d ", qans[i][j] );
		putchar ( '\n' );
	}
}

void upd ( int p, int val[] )
{
//	cerr << "upd : " << p << " : "; lp ( i, 0, V ) cerr << val[i] << " "; cerr << endl;
	lp ( i, 0, V ) tv[i] = val[i];
	lpdi ( i, V-2, 0 ) tv[i] += tv[i+1];
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd1 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast1.upd ( p, tv );
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd2 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast2.upd ( p, tv );
}

void query ( int l, int r, int ans[], bool flag )
{
//	cerr << "query : " << l << " " << r << " " << flag << endl;
	lp ( i, 0, V ) ans[i] = 0;
	if ( flag ){
		st1.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast1.query ( l, r, ans );
	}else{
		st2.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast2.query ( l, r, ans );
	}
}


#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define LD long double
#define SC(t,x) static_cast<t>(x)
#define AR(t) vector < t >
#define PII pair < int, int >
#define PLL pair < LL, LL >
#define PIL pair < int, LL >
#define PLI pair < LL, int >
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define PRF first
#define PRS second
#define INIT(ar,val) memset ( ar, val, sizeof ( ar ) )
#define lp(loop,start,end) for ( int loop = start; loop < end; ++loop )
#define lpd(loop,start,end) for ( int loop = start; loop > end; --loop )
#define lpi(loop,start,end) for ( int loop = start; loop <= end; ++loop )
#define lpdi(loop,start,end) for ( int loop = start; loop >= end; --loop )
#define qmax(a,b) (((a)>(b))?(a):(b))
#define qmin(a,b) (((a)<(b))?(a):(b))
#define qabs(a) (((a)>=0)?(a):(-(a)))

const int INF = 0x3fffffff;
const int SINF = 0x7fffffff;
const long long LINF = 0x3fffffffffffffff;
const long long SLINF = 0x7fffffffffffffff;
const int MAXN = 100007;
const int MAX = 131072;
const int MAXS = MAX * 2 + 7;
const int MAXV = 15;
const int V = 10;

class stT
{
public:
	void upd ( int p, int a[] )
	{
		p += MAX;
		lp ( i, 0, V ) data[p][i] += a[i];
		for ( p >>= 1; p; p >>= 1 ) lp ( i, 0, V ) data[p][i] = data[p<<1][i] + data[p<<1|1][i];
	}

	void query ( int l, int r, int a[] )
	{
		for ( l += MAX - 1, r += MAX + 1; l ^ r ^ 1; l >>= 1, r >>= 1 ){
			if ( ~l&1 ) lp ( i, 0, V ) a[i] += data[l^1][i];
			if ( r&1 ) lp ( i, 0, V ) a[i] += data[r^1][i];
		}
	}

private:
	int data[MAXS][MAXV];
}st1, st2, ast1, ast2;

int n, m;
bool vis[MAXN];
int ql[MAXN], qr[MAXN], qans[MAXN][MAXV];
AR(int) aql[MAXN], que[MAXN];
char s[MAXN];
int a[MAXN];
AR(int) aq[MAXN];
int stk[MAXN], top, smax[MAXN], sc[MAXN][MAXV];
int tv[MAXV];

void init ();
void input ();
void work ();

void upd ( int p, int val[] );
void query ( int l, int r, int ans[], bool flag );

int main()
{
	init();
	input();
	work();
}

void init ()
{
	// Init Everything Here

	ios::sync_with_stdio ( false );
}

void input ()
{
	// input method

	scanf ( "%d%d", &n, &m );
	scanf ( "%s", s+1 );
	lpi ( i, 1, m ) scanf ( "%d%d", &ql[i], &qr[i] );
}

void work ()
{
	// main work

	lpi ( i, 1, n ) a[i] = ( s[i] == '>' ) ? -1 : ( s[i] == '<' ) ? -2 : ( s[i] - '0' );

//	lpi ( i, 1, n ) cerr << a[i] << " "; cerr << endl;

	lpi ( i, 1, m ) aql[ql[i]].PB ( i ), que[qr[i]].PB ( i );

	int tl;
	lpi ( i, 1, n ){
//		cerr << "Begin : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }

		for ( auto x : aql[i] ) aq[stk[top]].PB ( x );

		if ( a[i] == -1 ){
			++top;
			stk[top] = i;
			smax[top] = -1;
			lp ( j, 0, V ) sc[top][j] = 0;
		}else if ( a[i] == -2 ){
			while ( top && ( smax[top] & 1 ) ){
				tl = stk[top];
				for ( auto x : aq[tl] ){
					if ( !vis[x] ){
						vis[x] = true;
						query ( ql[x], i, qans[x], false );
					}
				}
				upd ( tl, sc[top] );
				--top;
			}
			for ( auto x : aq[stk[top]] ){
				if ( !vis[x] ){
					vis[x] = true;
					query ( ql[x], i, qans[x], false );
				}
			}
			aq[stk[top]].clear ();
			upd ( stk[top], sc[top] );
			lp ( j, 0, V ) sc[top][j] = 0;
			smax[top] = -1;
		}else{
			smax[top] = qmax ( smax[top], a[i] );
			++sc[top][a[i]];
			INIT ( tv, 0 );
			tv[a[i]] = 1;
			st1.upd ( i, tv );
			if ( a[i] ) tv[a[i]-1] = 1;
			st2.upd ( i, tv );
		}

		for ( auto x : que[i] ){
			if ( !vis[x] ){
				vis[x] = true;
				query ( ql[x], i, qans[x], true );
			}
		}

//		cerr << "End : " << i << endl;
//		lpi ( i, 0, top ) { cerr << i << " " << stk[i] << " " << smax[i] << " : "; for ( auto x : aq[stk[i]] ) cerr << x << " "; cerr << endl; }
	}

	lpi ( i, 1, m ){
		lp ( j, 0, V ) printf ( "%d ", qans[i][j] );
		putchar ( '\n' );
	}
}

void upd ( int p, int val[] )
{
//	cerr << "upd : " << p << " : "; lp ( i, 0, V ) cerr << val[i] << " "; cerr << endl;
	lp ( i, 0, V ) tv[i] = val[i];
	lpdi ( i, V-2, 0 ) tv[i] += tv[i+1];
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd1 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast1.upd ( p, tv );
	lp ( i, 0, V ) tv[i] = tv[i+1];
	tv[V-1] = 0;
//	cerr << "upd2 : " << p << " : "; lp ( i, 0, V ) cerr << tv[i] << " "; cerr << endl;
	ast2.upd ( p, tv );
}

void query ( int l, int r, int ans[], bool flag )
{
//	cerr << "query : " << l << " " << r << " " << flag << endl;
	lp ( i, 0, V ) ans[i] = 0;
	if ( flag ){
		st1.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast1.query ( l, r, ans );
	}else{
		st2.query ( l, r, ans );
//		cerr << "val1 : "; lp ( i, 0, V ) cerr << ans[i] << " "; cerr << endl;
		ast2.query ( l, r, ans );
	}
}


//lxrtxdy!
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int INF = 1e9;
const double EPS = 1e-9;
const double PI = acos(-1.);
const int MX = 2e6;
int cnt[10][MX];
int pos = 1;

char s[100500];
bool used[100500];
int fst[100500];
int lf[100500];
int rg[100500];

int ip;
int nxtr[100500], nxtl[100500];
void mrigh()
{
	rg[ip] = min(rg[ip], pos);
	while(s[nxtr[ip]] == ' ')
	{
		rg[nxtr[ip]] = min(rg[nxtr[ip]], pos);
		nxtr[ip] = nxtr[nxtr[ip]];
	}
	ip = nxtr[ip];
}
void mleft()
{
	lf[ip] = min(lf[ip], pos);
	while(s[nxtl[ip]] == ' ')
	{
		lf[nxtl[ip]] = min(lf[nxtl[ip]], pos);
		nxtl[ip] = nxtl[nxtl[ip]];
	}
	ip = nxtl[ip];
}

void build(int st)
{
	ip = st;
	int dir = 1;
	while (true)
	{
		if (ip < st || s[ip] == 0)
			return;
		used[ip] = true;
		fst[ip] = min(fst[ip], pos);
		int cur = ip;
		if (s[ip] == '>')
		{
			mrigh();
			if (s[ip] == '>' || s[ip] == '<')
				s[cur] = ' ';
			dir = 1;
			continue;
		}
		if (s[ip] == '<')
		{
			mleft();
			if (s[ip] == '>' || s[ip] == '<')
				s[cur] = ' ';
			dir = -1;
			continue;
		}
		cnt[s[ip] - '0'][pos] = 1;
		++pos;
		if (s[ip] == '0') s[ip] = ' ';
		else
			--s[ip];
		if (dir > 0)
			mrigh();
		else
			mleft();
	}
}

int main()
{
#ifdef _DEBUG
	freopen("Dtest.txt", "r", stdin);
#endif
	int n, q;
	scanf("%d%d%s", &n, &q, &s);
	int len = strlen(s);
	for (int i = 0; i <= len; ++i)
	{
		nxtl[i] = i - 1;
		nxtr[i] = i + 1;
		fst[i] = INF;
		lf[i] = INF;
		rg[i] = INF;
	}
	for (int i = 0; i < len; ++i)
	{
		if (!used[i])
			build(i);
	}
	for (int j = 0; j < 10; ++j)
	for (int i = 1; i < pos; ++i)
	{
		cnt[j][i] += cnt[j][i - 1];
	}
	for (int i = 0; i < q; ++i)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		--l;
		--r;
		int frm = fst[l] - 1;
		int to = min(lf[l], rg[r]) - 1;
		to = min(to, pos - 1);
		for (int j = 0; j < 10; ++j)
		{
			printf("%d ", cnt[j][to] - cnt[j][frm]);
		}
		puts("");
	}
	return 0;
}
//hellobig_tq
//orzlxr!//hello//hello


#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif

using namespace std;

const int maxn = 1e5 + 10;

int n, q, clk, fst[maxn], out[maxn], pre[maxn], nxt[maxn], cnt_fst[maxn][10], cnt_out[maxn][10], cnt[10];
char s[maxn];

int main(int argc, char *argv[]) {
	scanf("%d%d", &n, &q);
	scanf("%s", s + 1);
	for (int i = 1; i <= n; ++i) {
		pre[i] = i - 1;
		nxt[i] = i + 1;
	}
	nxt[0] = 1;
	pre[n + 1] = n;
	s[0] = '>';
	for (int i = nxt[0], dir = 1; i <= n; ) {
		++clk;
		if(!i) {
			dir = 1;
			i = nxt[i];
			continue;
		}
		if(!fst[i]) {
			fst[i] = clk;
			memcpy(cnt_fst[i], cnt, sizeof cnt);
		}
		if(s[i] == '<') {
			dir = 0;
		}
		if(s[i] == '>') {
			dir = 1;
		}
		int j = (dir == 1 ? nxt[i] : pre[i]);
		if(s[i] == '<' || s[i] == '>') {
			if(j <= n) {
				if(s[j] == '<' || s[j] == '>') {
					pre[nxt[i]] = pre[i];
					nxt[pre[i]] = nxt[i];
				}
			}
		}
		else {
			++cnt[s[i] - '0'];
			if(s[i] == '0') {
				pre[nxt[i]] = pre[i];
				nxt[pre[i]] = nxt[i];
			}
			else {
				--s[i];
			}
		}
		i = j;
		while(j + 1 <= n && fst[j + 1] && !out[j + 1]) {
			out[++j] = clk;
			memcpy(cnt_out[j], cnt, sizeof cnt);
		}
	}
	fst[n + 1] = ++clk;
	memcpy(cnt_fst[n + 1], cnt, sizeof cnt);
	while(q--) {
		int l, r;
		scanf("%d%d", &l, &r);
		if(!out[l] || out[l] > fst[r + 1]) {
			for (int c = 0; c < 10; ++c) {
				printf("%d%c", cnt_fst[r + 1][c] - cnt_fst[l][c], " \n"[c == 9]);
			}
		}
		else {
			for (int c = 0; c < 10; ++c) {
				printf("%d%c", cnt_out[l][c] - cnt_fst[l][c], " \n"[c == 9]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif

using namespace std;

const int maxn = 1e5 + 10;

int n, q, clk, fst[maxn], out[maxn], pre[maxn], nxt[maxn], cnt_fst[maxn][10], cnt_out[maxn][10], cnt[10];
char s[maxn];

int main(int argc, char *argv[]) {
	scanf("%d%d", &n, &q);
	scanf("%s", s + 1);
	for (int i = 1; i <= n; ++i) {
		pre[i] = i - 1;
		nxt[i] = i + 1;
	}
	nxt[0] = 1;
	pre[n + 1] = n;
	s[0] = '>';
	for (int i = nxt[0], dir = 1; i <= n; ) {
		++clk;
		if(!i) {
			dir = 1;
			i = nxt[i];
			continue;
		}
		if(!fst[i]) {
			fst[i] = clk;
			memcpy(cnt_fst[i], cnt, sizeof cnt);
		}
		if(s[i] == '<') {
			dir = 0;
		}
		if(s[i] == '>') {
			dir = 1;
		}
		int j = (dir == 1 ? nxt[i] : pre[i]);
		if(s[i] == '<' || s[i] == '>') {
			if(j <= n) {
				if(s[j] == '<' || s[j] == '>') {
					pre[nxt[i]] = pre[i];
					nxt[pre[i]] = nxt[i];
				}
			}
		}
		else {
			++cnt[s[i] - '0'];
			if(s[i] == '0') {
				pre[nxt[i]] = pre[i];
				nxt[pre[i]] = nxt[i];
			}
			else {
				--s[i];
			}
		}
		if(j < i && !out[i]) {
			out[i] = clk;
			memcpy(cnt_out[i], cnt, sizeof cnt);
		}
		i = j;
	}
	fst[n + 1] = ++clk;
	memcpy(cnt_fst[n + 1], cnt, sizeof cnt);
	while(q--) {
		int l, r;
		scanf("%d%d", &l, &r);
		if(!out[l] || out[l] > fst[r + 1]) {
			for (int c = 0; c < 10; ++c) {
				printf("%d%c", cnt_fst[r + 1][c] - cnt_fst[l][c], " \n"[c == 9]);
			}
		}
		else {
			for (int c = 0; c < 10; ++c) {
				printf("%d%c", cnt_out[l][c] - cnt_fst[l][c], " \n"[c == 9]);
			}
		}
	}
	return 0;
}