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

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)n; ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cout<<*i<<" "; cout<<endl; }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<string, int> P;

int main(){
  int N,A,S,G;
  while(cin>>N>>A>>S>>G,N){
    vector<int> to[40]; vector<string> spell[40];
    REP(i,A){
      int u,v; string s;
      cin>>u>>v>>s;
      to[u].push_back(v);
      spell[u].push_back(s);
    }
    priority_queue<P, vector<P>, greater<P> > que;
    que.push(P("", S));
    string ans = "NO";
    set<P> memo;
    bool reachable[40][40]={};
    REP(i,N)reachable[i][i] = true;
    REP(i,N)REP(j,to[i].size())reachable[i][to[i][j]] = true;
    REP(k,N)REP(i,N)REP(j,N)reachable[i][j] |= reachable[i][k] & reachable[k][j];
    if(!reachable[S][G]) goto OUT;
    while(!que.empty()){
      P p = que.top(); que.pop();
      if(p.second == G){
        ans = p.first;
        break;
      }
      if((int)p.first.size() > N*6){
        break;
      }
      if(memo.count(p))continue;
      memo.insert(p);
      REP(i,to[p.second].size()){
        int next = to[p.second][i];
        if(reachable[next][G]) que.push(P(p.first + spell[p.second][i], next));
      }
    }
OUT:
    cout<<ans<<endl;
  }
  return 0;
}