class Arrow
  attr_reader :source, :sink, :label
   
  def initialize(source, sink, label)
    @source = source
    @sink = sink
    @label = label
  end
end
 
class Result
  attr_reader :target, :spell
 
  def initialize(target, spell)
    @target = target
    @spell = spell
  end
end
 
def advance(table, n, goes, arrows)
  (0...n).each do |node|
    best = table[node]
    goes[node].each do |arrow|
      result = table[arrow.sink]
      next unless result
      test = arrow.label + result.spell
      if !best || test < best.spell
        best = Result.new(arrow.sink, test)
      end
    end
    table[node] = best if best
  end
end
 
def has_cycle(table, result, n)
  used = [false] * n
  loop do
    node = result.target
    return false unless node
    return true if used[node]
    used[node] = true
    result = table[node]
  end
end
 
def work(n, arrows, start, goal)
  goes = (0...n).map{[]}
  arrows.each do |arrow|
    goes[arrow.source] << arrow
  end
  table = [nil] * n
  table[goal] = Result.new(nil, '')
  n.times do
    advance(table, n, goes, arrows)
  end
  return nil unless table[start]
  (n*5).times do
    advance(table, n, goes, arrows)
  end
  result = table[start]
  has_cycle(table, result, n) ? nil : result.spell
end
 
loop do
  n, a, s, g = STDIN.gets.split.map(&:to_i)
  break if n == 0
 
  arrows = (0...a).map do |i|
    x, y, lab = STDIN.gets.split
    x = x.to_i
    y = y.to_i
    Arrow.new(x, y, lab)
  end
 
  start = s
  goal = g
 
  puts work(n, arrows, start, goal) || 'NO'
end