#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cassert>
#include<sstream>
#include<deque>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define MAX 50
#define MAX2 404
#define inf (string(400,'Z'))
using namespace std;
struct P
{
  int from,to;
  string cost;
  P(int from=-1,int to=-1,string cost="$"):from(from),to(to),cost(cost){}
};
int V,E,s,g;
P es[MAX2];
string d[MAX];

bool check(string a,string b)//a < b?
{
  return a < b;
}

bool Bellman_Ford()
{
  rep(i,MAX)d[i]="$";
  rep(i,E)
    if(es[i].from == s && (d[es[i].to] == "$" || d[es[i].to] > es[i].cost))
      d[es[i].to] = es[i].cost;

  int loop = V*8;
  rep(xyz,loop)
    {
      rep(i,E)
	{
	  P p = es[i];

	  if(d[p.from] == "$")continue;
	  if(d[p.to] == "$")
	    {
	      d[p.to] = p.cost + d[p.from];
	      if(p.to == g && xyz >= V)return true;
	      continue;
	    }

	  if(d[p.to] != "$" && check(p.cost + d[p.from],d[p.to]))
	    {
	      d[p.to] = p.cost + d[p.from];

	      if(p.to == g && xyz >= V)return true;
	    }

	}
    }
  return false;
}

int main()
{
  //謎の挙動
  //cout << ("ace" < "abc") << endl;
  //cout << ("ace" < "abc") << " ; " << min("ace","abc") << endl;
  while(cin >> V >> E >> g >> s,V|E|s|g)
    {
      rep(i,E)
	cin >> es[i].to >> es[i].from >> es[i].cost;
      if(Bellman_Ford())
	{
	  cout << "NO" << endl;
	  continue;
	}
  
      if(d[g] == "$")cout << "NO" << endl;
      else          cout << d[g] << endl;
    }
  return 0;
}



/*
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#define MAX_V 50
using namespace std;

struct Edge
{
  int from,to;
  string cost;
  Edge(int from=0,int to=0,string cost=""):from(from),to(to),cost(cost){}
};

string rd[MAX_V],d[MAX_V];
vector<Edge> rG,G;
int V,E,s,g,rs,rg;

bool check(Edge e)
{
  //cout << "e.from = "<< e.from << endl;
  if(d[e.from] == "X")
    return false;
  if(d[e.to] == "X")
    return true;
  string from,to;
  from = d[e.from]+e.cost;
  to = d[e.to]!="X"?d[e.to]:"";
  //cout << "------------" << endl;
  //cout << from << " -X- " << to << endl;
  //cout << "------------" << endl;
  for(int i=0;i<min(from.size(),to.size());i++)
    {
      if(from[i] == to[i])
	continue;
      if(from[i] > to[i])
	return false;
      else if(from[i] < to[i])
	return true;
    }

  if(from.size() == to.size())
    return false;
  else if(from.size() > to.size())
    return false;
  else 
    return true;
}

bool Exe()
{
  for(int i=0;i<V;i++)d[i] = "X";
  d[s] = "";
  for(int i=0;i<V;i++)
    {
      for(int j=0;j<E;j++)
	{
	  Edge e = G[j];
	  if(check(e))
	    {
	      d[e.to] = d[e.from]+e.cost;
	      //cout << "d["<<e.to<<"] = " << d[e.to] << endl;
	      //cout << "d["<<e.from<<"] = "<< d[e.from] << endl;
	      //cout << "e.cost = " << e.cost << endl;
	      //cout << "e.cost + d["<<e.from<<"] = "<< e.cost+d[e.from] << endl;
	      //cout << endl;
	      if(i == V-1)
		{
		  return false;
		}
	    }
	}
    }
  return true;
}

bool rcheck(Edge e)
{
  //cout << "e.from = "<< e.from << endl;
  if(rd[e.from] == "X")
    return false;
  if(rd[e.to] == "X")
    return true;
  string from,to;
  from = e.cost+rd[e.from];
  to = rd[e.to]!="X"?rd[e.to]:"";
  //cout << "------------" << endl;
  //cout << from << " -X- " << to << endl;
  //cout << "------------" << endl;
  for(int i=0;i<min(from.size(),to.size());i++)
    {
      if(from[i] == to[i])
	continue;
      if(from[i] > to[i])
	return false;
      else if(from[i] < to[i])
	return true;
    }

  if(from.size() == to.size())
    return false;
  else if(from.size() > to.size())
    return false;
  else 
    return true;
}


bool rExe()
{
  string rdp[V];
  for(int i=0;i<V;i++)rd[i] = "X";
  for(int i=0;i<V;i++)rdp[i] = rd[i];
  rd[rs] = rdp[rs] =  "";


  for(int i=0;i<V;i++)
    {


      
      for(int j=0;j<E;j++)
	{
	  Edge e = rG[j];
	  if(rcheck(e))
	    {
	      rd[e.to] = e.cost+rd[e.from];
	      //cout << "d["<<e.to<<"] = " << d[e.to] << endl;
	      //cout << "d["<<e.from<<"] = "<< d[e.from] << endl;
	      //cout << "e.cost = " << e.cost << endl;
	      //cout << "e.cost + d["<<e.from<<"] = "<< e.cost+d[e.from] << endl;
	      //cout << endl;
	      if(i == V-1)
		{
		  cout << "NO" << endl;
		  return false;
		}
	    }
	}
      for(int i=0;i<V;i++)
	rdp[i] = rd[i];
    }
  if(rdp[rg] != "X")
    cout << rdp[rg] << endl;
  else
    cout << "NO" <<endl;
  return true;
}

int main()
{


  while(cin >> V >> E >> s >> g,V|E|s|g)
    {
      G.resize(E);
      rG.resize(E);
      rs = g;
      rg = s;
      for(int i=0;i<E;i++)
	{
	  int x,y;
	  string lab;
	  cin >> x >> y >> lab;
       	   G[i] = Edge(x,y,lab);
	  rG[i] = Edge(y,x,lab);
	}
      bool res,rres;
      //res = Exe();
      rres = rExe();
      //cout << d[g] << " " << rd[rg] << endl;  
      //if(!res || !rres || d[g] == "X" || rd[rg] == "X" || rd[rg] != d[g])
      //cout << "NO" << endl;
      //else
      //cout << d[g] << endl;
      //for(int i=0;i<V;i++)cout << d[i] << " ";
      //cout << endl;
    }
  return 0;
}
*/

Measured memory_bytes: 1844