#include <bits/stdc++.h>
using namespace std;
struct Data {
  int Pos, Number;
};
bool operator<(Data A, Data B) { return A.Pos > B.Pos; }
int Get() {
  char c;
  while (c = getchar(), c < '0' || c > '9')
    ;
  int X = 0;
  while (c >= '0' && c <= '9') {
    X = X * 10 + c - 48;
    c = getchar();
  }
  return X;
}
int GetTape() {
  char c;
  while (c = getchar(), (c < '0' || c > '9') && (c != '<') && (c != '>'))
    ;
  if (c >= '0' && c <= '9') return c - 48;
  return (c == '<') ? -1 : -2;
}
const int inf = 1000000000;
int N;
int Tape[100002];
vector<Data> Q[100001];
set<int> AllPos;
bool Flag[100001], Out[100000];
int Sum[10], Ans[100000][10];
int Next(set<int>::iterator P, int Direction) {
  return *((Direction == 1) ? (++P) : (--P));
}
int Work(set<int>::iterator P, int Low) {
  int Direction = 1;
  static Data Stack[100000];
  int Top = 0, Far = Low;
  priority_queue<Data> Queue;
  while (true) {
    Far = max(Far, *P);
    if (*P > Low && *P <= N && !Flag[*P]) {
      for (int i = 0; i < Q[*P].size(); i++) {
        for (int j = 0; j < 10; j++) Ans[Q[*P][i].Number][j] = -Sum[j];
        Stack[Top++] = (Data){*P, Q[*P][i].Number};
        Queue.push((Data){Q[*P][i].Pos, Q[*P][i].Number});
      }
      Flag[*P] = true;
    }
    while (Top && *P < Stack[Top - 1].Pos) {
      Top--;
      int V = Stack[Top].Number;
      if (Out[V]) continue;
      Out[V] = true;
      for (int i = 0; i < 10; i++) Ans[V][i] += Sum[i];
    }
    while (!Queue.empty() && *P > Queue.top().Pos) {
      int V = Queue.top().Number;
      Queue.pop();
      if (Out[V]) continue;
      Out[V] = true;
      for (int i = 0; i < 10; i++) Ans[V][i] += Sum[i];
    }
    if (*P <= Low || *P > N) break;
    if (Tape[*P] >= 0) {
      Sum[Tape[*P]]++;
      int Q = Next(P, Direction);
      Tape[*P]--;
      if (Tape[*P] < 0) AllPos.erase(P);
      P = AllPos.find(Q);
    } else {
      Direction = (Tape[*P] == -1) ? -1 : 1;
      int Q = Next(P, Direction);
      if (Tape[Q] < 0) AllPos.erase(P);
      P = AllPos.find(Q);
    }
  }
  return Far;
}
int main() {
  N = Get();
  int M = Get();
  for (int i = 1; i <= N; i++) Tape[i] = GetTape();
  for (int i = 0; i < M; i++) {
    int L = Get(), R = Get();
    Q[L].push_back((Data){R, i});
  }
  for (int i = 0; i <= N + 1; i++) AllPos.insert(i);
  memset(Flag, 0, sizeof(Flag));
  memset(Out, 0, sizeof(Out));
  memset(Sum, 0, sizeof(Sum));
  memset(Ans, 0, sizeof(Ans));
  int Max = 0;
  while (Max < N) Max = Work(AllPos.find(Max + 1), Max);
  for (int i = 0; i < M; i++)
    for (int j = 0; j < 10; j++) {
      printf("%d", Ans[i][j]);
      putchar((j == 9) ? '\n' : ' ');
    }
  return 0;
}
