
class Arrow
  attr_reader :source, :sink, :label

  def initialize(source, sink, label)
    @source = source
    @sink = sink
    @label = label
  end
end

def push(queue, label)
  size = queue.size
  index = queue.index{|entry| entry[0] >= label} || size
  return queue[index][1] if index < size && queue[index][0] == label

  return nil if index > 0 && !label.start_with?(queue[index - 1][0])
  queue.slice!(index..-1) if index < size && !queue[index][0].start_with?(label)

  nodes = {}
  queue.insert(index, [label.dup, nodes])
  nodes
end

def calc(n, arrows, start, goal)
  ins = Array.new(n){[]}
  arrows.each do |arrow|
    ins[arrow.sink] << arrow.source
  end

  reachable_from = {}
  stack = [goal]
  until stack.empty?
    node = stack.pop
    reachable_from[node] = true
    ins[node].each do |source|
      stack << source unless reachable_from[source]
    end
  end

  return nil unless reachable_from[start]
  arrows.select!{|arrow| reachable_from[arrow.sink]}

  outs = Array.new(n){[]}
  arrows.each do |arrow|
    outs[arrow.source] << arrow
  end

  limit = n * arrows.map{|arrow| arrow.label.size}.max

  result = ''
  queue = [['', {start => true}]]
  until queue.empty?
    label, nodes = queue.shift
    result << label
    return result if nodes[goal]
    return nil if result.size > limit

    size = label.size
    queue.each do |key, value|
      key.slice!(0...size)
    end

    nodes.each do |node, _|
      outs[node].each do |arrow|
        new_nodes = push(queue, arrow.label)
        new_nodes[arrow.sink] = true if new_nodes
      end
    end
  end
  nil
end

loop do
  n, a, s, g = gets.split.map(&:to_i)
  break if n == 0

  arrows = (0...a).map{
    x, y, lab = gets.split
    Arrow.new(x.to_i, y.to_i, lab)
  }

  puts calc(n, arrows, s, g) || 'NO'
end