// AOJ 1169
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#define rep(i,a) for(int i=0;i<(a);++i)

const std::string INF = "NO";

struct edge
{
	int from, to;
	std::string lab;

	edge( int from, int to, const std::string &lab )
	:	from(from), to(to), lab(lab)
	{}
};

int n, a, s, g;
std::vector<edge> es;
int maxL;

int main()
{
	while( scanf( "%d%d%d%d", &n, &a, &s, &g ), n|a|s|g )
	{
		es.clear();
		maxL = 0;

		rep( i, a )
		{
			int x, y;
			char lab[7];

			scanf( "%d%d%s", &x, &y, lab );

			es.push_back( edge( x, y, lab ) );

			maxL = std::max<int>( maxL, strlen(lab) );
		}

		std::vector<std::string> d( n, INF );
		d[g] = "";

		rep( i, n*(maxL+1) )
		{
			auto nxt = d;

			rep( j, a ) if( d[es[j].to] != INF && (nxt[es[j].from] == INF || nxt[es[j].from] > es[j].lab + d[es[j].to]) )
			{
				nxt[es[j].from] = es[j].lab + d[es[j].to];

				if( es[j].from == s && i >= n )
				{ puts("NO"); goto end; }
			}

			d.swap(nxt);
		}

		printf( "%s\n", d[s].c_str() );

end:;
	}

	return 0;
}