#include <bits/stdc++.h>
#pragma comment(linker, / STACK : 2000010)
using namespace std;
struct Node {
  string data;
  Node* firstChild;
  Node* nextSibling;
  long id;
  long tagId;
  Node(string aData, Node* aChild = NULL, Node* aSibling = NULL, long aId = 0) {
    data = aData;
    firstChild = aChild;
    nextSibling = aSibling;
    tagId = aId;
  }
};
long PreOrder(Node* apRoot, int aPos);
Node* BuildNaryTree(string htmlDoc);
void PushToStack(Node* node);
void PopFromStack(Node** node);
class HashTable {
 public:
  HashTable(long aSize);
  ~HashTable();
  void put(string aTag);
  bool contains(string aTag);
  long get(string aTag);
  void remove(string aTag);
  long size();

 private:
  std::unordered_map<string, long> mLookupTable;
};
const int MaxQueryCount = 5000;
const long MaxNodeCount = 350000;
string* gQuery = NULL;
long* lQuery = NULL;
int gQTagCount = 0;
HashTable* g_pHashTable = NULL;
long gStack[MaxNodeCount] = {0};
long gStackTop = -1;
Node* gNode[MaxNodeCount] = {0};
long gNodeCount = 0;
void PushToStack(Node* node) {
  gStackTop++;
  if (gStackTop > MaxNodeCount) {
    printf("\n Stack Overflow machi...");
    return;
  }
  gStack[gStackTop] = (long)node;
}
void PopFromStack(Node** node) {
  if (gStackTop == -1) {
    *node = NULL;
    return;
  }
  *node = (Node*)gStack[gStackTop];
  gStackTop -= 1;
}
Node* BuildNaryTree(string htmlDoc) {
  long nId = 0;
  Node* pParent = new Node("", NULL, NULL, -100);
  Node* root = pParent;
  long idx = 1;
  Node* topOfStackNode = NULL;
  bool prevTagClosed = false;
  bool createNode = false;
  string tag;
  gNode[0] = pParent;
  while (idx < htmlDoc.size()) {
    if (htmlDoc[idx] == '/') {
      int i = idx + 1;
      while (htmlDoc[i] && htmlDoc[i] != '>') i++;
      PopFromStack(&topOfStackNode);
      prevTagClosed = true;
      idx = i + 2;
    } else {
      Node* currentNode = NULL;
      int j = idx + 1;
      while (htmlDoc[j] && htmlDoc[j] != '/' && htmlDoc[j] != '>') j++;
      tag = htmlDoc.substr(idx, j - idx);
      nId += 1;
      long tagId;
      if (g_pHashTable->contains(tag) == false) {
        g_pHashTable->put(tag);
      }
      tagId = g_pHashTable->get(tag);
      currentNode = new Node(tag, NULL, NULL, tagId);
      gNode[++gNodeCount] = currentNode;
      PushToStack(currentNode);
      if (prevTagClosed) {
        topOfStackNode->nextSibling = currentNode;
        pParent = currentNode;
        prevTagClosed = false;
      } else {
        pParent->firstChild = currentNode;
        pParent = pParent->firstChild;
      }
      if (htmlDoc[j] == '/') {
        idx = j;
        continue;
      } else {
        idx = j + 2;
      }
    }
  }
  return root;
}
void fillQueryArray(string query) {
  int index = 0;
  int tagIndex = 0;
  {
    if (gQuery) {
      delete[] gQuery;
      gQuery = NULL;
    }
  };
  {
    if (lQuery) {
      delete[] lQuery;
      lQuery = NULL;
    }
  };
  gQuery = new string[MaxQueryCount];
  lQuery = new long[MaxQueryCount];
  while (index < query.size()) {
    if (query[index] == ' ') {
      tagIndex += 1;
    } else {
      gQuery[tagIndex] += query[index];
    }
    index += 1;
  }
  gQTagCount = tagIndex + 1;
  for (int i = 0; i < gQTagCount; i++) {
    if (g_pHashTable->contains(gQuery[i])) {
      lQuery[i] = g_pHashTable->get(gQuery[i]);
    } else {
      lQuery[i] = -1;
    }
  }
}
long PreOrder(Node* apRoot, int aPos) {
  long sum = 0;
  int savePos = aPos;
  if (apRoot == NULL) return 0;
  if (apRoot->tagId == lQuery[aPos]) {
    if (aPos == gQTagCount - 1) {
      sum = 1;
    } else
      aPos++;
  }
  return sum + PreOrder(apRoot->firstChild, aPos) +
         PreOrder(apRoot->nextSibling, savePos);
}
string readHtmlDoc() {
  char sHtmlDoc[1000010] = {0};
  string htmlDoc;
  cin.getline(sHtmlDoc, 1000010);
  for (long i = 0; sHtmlDoc[i]; i++) {
    htmlDoc += sHtmlDoc[i];
  }
  return htmlDoc;
}
int readn() {
  int n = 0;
  char snumber[4] = {0};
  cin.getline(snumber, 4);
  n = atoi(snumber);
  return n;
}
string readQuery() {
  string query;
  int j = 0;
  char ch = 0;
  do {
    ch = getchar();
    if ((ch == '\r') || (ch == '\n')) {
      break;
    }
    query += ch;
    ++j;
  } while (j < MaxQueryCount);
  return query;
}
int main() {
  Node* root = NULL;
  int n = 0;
  string htmlDoc;
  string query;
  g_pHashTable = new HashTable(100);
  if (g_pHashTable == NULL) {
    return -1;
  }
  htmlDoc = readHtmlDoc();
  root = BuildNaryTree(htmlDoc);
  n = readn();
  for (int i = 0; i < n; i++) {
    query = readQuery();
    fillQueryArray(query);
    cout << PreOrder(root, 0) << endl;
    {
      if (gQuery) {
        delete[] gQuery;
        gQuery = NULL;
      }
    };
    {
      if (lQuery) {
        delete[] lQuery;
        lQuery = NULL;
      }
    };
  }
  Node* pNode = NULL;
  for (int iLoop = gNodeCount; iLoop >= 0; iLoop--) {
    {
      if (gNode[iLoop]) {
        delete gNode[iLoop];
        gNode[iLoop] = NULL;
      }
    };
  }
  {
    if (g_pHashTable) {
      delete g_pHashTable;
      g_pHashTable = NULL;
    }
  };
  return 0;
}
HashTable::HashTable(long aSize) {}
HashTable::~HashTable() { mLookupTable.clear(); }
void HashTable::put(string aTag) {
  pair<string, long> item;
  item.first = aTag;
  item.second = mLookupTable.size();
  mLookupTable.insert(item);
}
bool HashTable::contains(string aTag) {
  bool isAvailable = true;
  std::unordered_map<string, long>::iterator it = mLookupTable.find(aTag);
  if (it == mLookupTable.end()) {
    isAvailable = false;
  }
  return isAvailable;
}
long HashTable::get(string aTag) {
  long tagIndex = -1;
  std::unordered_map<string, long>::iterator it = mLookupTable.find(aTag);
  if (it == mLookupTable.end()) {
    return tagIndex;
  }
  tagIndex = it->second;
  return tagIndex;
}
void HashTable::remove(string aTag) {
  std::unordered_map<string, long>::iterator it = mLookupTable.find(aTag);
  if (it == mLookupTable.end()) {
    return;
  }
  mLookupTable.erase(it);
}
long HashTable::size() { return mLookupTable.size(); }
