#include <cstdio>
#include <set>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>

using namespace std;

typedef pair<string, int> state;
const int MAX_N = 42;
int N, start, goal;
bool G[MAX_N][MAX_N];
vector<string> ws[MAX_N][MAX_N];
set<string> dist[MAX_N][MAX_N];

inline bool strictLarge(string a, string b){
	int len = min(a.length(), b.length());
	for(int i=0; i<len; i++){
		if(a[i] != b[i]) return a[i]>b[i];
	}
	return false;
}

void init(){
	for(int k=0; k<N; k++){
		for(int i=0; i<N; i++){
			for(int j=0; j<N; j++){
				G[i][j] |= (G[i][k] && G[k][j]);
			}
		}
	}
	for(int i=0; i<N; i++)if(!G[i][goal] && i!=goal){
		for(int j=0; j<N; j++){
			G[j][i] = false;
		}
	}
}

string solve(){
	init();
	if(!G[start][goal]){
		return "NO";
	}
	priority_queue< state, vector<state>, greater<state> > Q;
	vector< set<string> > dist(N);

	Q.push( make_pair("", start) );
	dist[start].insert("");

	while(!Q.empty()){
		state tp = Q.top(); Q.pop();
		string str = tp.first;
		if(str.length() > 6*N){
			return "NO";
		}
		int cur = tp.second;
		if(cur == goal){
			return str;
		}
		if(strictLarge(str, *dist[cur].rbegin())){
			continue;
		}
		for(int i=0; i<N; i++)if(G[i][goal] || i==goal){
			for(int j=0; j<(int)ws[cur][i].size(); j++){
				string wd = str + ws[cur][i][j];
				if(dist[i].find(wd) == dist[i].end()){
					dist[i].insert(wd);
					Q.push( make_pair(wd, i) );
				}
			}
		}
	}
	return "ERROR";
}

int main(){
	int A;
	while(scanf("%d%d%d%d",&N,&A,&start,&goal), N){
		for(int i=0; i<N; i++)for(int j=0; j<N; j++) G[i][j] = false;
		for(int i=0; i<N; i++)for(int j=0; j<N; j++) ws[i][j].clear();
		for(int i=0; i<A; i++){
			char buf[10];
			int x, y;
			scanf("%d%d %s ", &x, &y, buf);
			G[x][y] = true;
			ws[x][y].push_back(string(buf));
		}
		puts(solve().c_str());
	}
	return 0;
}