#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
int n,m,s,g;
vector<pair<int,string> >edge[45];
string dp[45];
struct S{
	int v; string s;
	bool operator <(const S &a)const{
		return s > a.s;
	}
	S(int a,string b){
		v = a; s = b;
	}
};
int a[3005],b[3005]; string c[3005];
int main(){
	while(1){
		scanf("%d%d%d%d",&n,&m,&s,&g);
		if(n==0) return 0;
		for(int i=0;i<n;i++){
			edge[i].clear();
			dp[i] = "1";
		}
		for(int i=0;i<m;i++){
			cin >> a[i] >> b[i] >> c[i];
			edge[b[i]].pb(mp(a[i],c[i]));
		}
		
		priority_queue<S>que;
		que.push(S(g,"")); dp[g] = "";
		while(!que.empty()){
			S t = que.top(); que.pop();
			if(dp[t.v] != "1" && dp[t.v] < t.s) continue;
			if(t.s.size() > 500) continue;
			for(int i=0;i<edge[t.v].size();i++){
				string nex = edge[t.v][i].sc;
				nex += t.s;
				if(dp[edge[t.v][i].fi] == "1" || dp[edge[t.v][i].fi] > nex){
					dp[edge[t.v][i].fi] = nex;
					que.push(S(edge[t.v][i].fi,nex));
				}
			}
		}
		if(dp[s].size() >= 250 || dp[s] == "1") puts("NO");
		else cout << dp[s] << endl;
	}
}