#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ld=long double;
using P=pair<ll,ll>;
#define MOD 1000000007ll
#define INF 1000000000ll
#define EPS 1e-10
#define FOR(i,n,m) for(ll i=n;i<(ll)m;i++)
#define REP(i,n) FOR(i,0,n)
#define DUMP(a) REP(d,a.size()){cout<<a[d];if(d!=a.size()-1)cout<<" ";else cout<<endl;}
#define ALL(v) v.begin(),v.end()
#define UNIQUE(v) sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
#define pb push_back

struct Edge {
	ll to;
	string lab;
};

ll n,a,s,g;
string INFSTR="";

string solve() {
	vector<vector<Edge>> grp(n);
	REP(i,a) {
		ll x,y;
		string lab;
		cin>>x>>y>>lab;
		grp[x].pb(Edge{y,lab});
	}
	vector<vector<string>> dir(n,vector<string>(601,INFSTR));
	dir[s][0]="";
	priority_queue<pair<string,ll>,vector<pair<string,ll>>,greater<pair<string,ll>>> q;
	q.push(make_pair("",s));
	while(!q.empty()) {
		string str=q.top().first;
		ll p=q.top().second;
		q.pop();
		if(dir[p][(ll)str.size()]!=str) continue;
		REP(i,grp[p].size()) {
			string cost=grp[p][i].lab;
			ll np=grp[p][i].to;
			if((str+cost).size()>600) continue;
			if(str+cost<dir[np][(str+cost).size()]) {
				dir[np][(str+cost).size()]=str+cost;
				q.push(make_pair(str+cost,np));
			}
		}
	}
	string ret=INFSTR;
	REP(i,601) ret=min(ret,dir[g][i]);
	if(ret==INFSTR||(ll)ret.size()>250) return "NO";
	return ret;
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	REP(i,600) INFSTR+='z';
	while(1) {
		cin>>n>>a>>s>>g;
		if(n==0) break;
		cout<<solve()<<endl;
	}
}

