A substring of some string is called the most frequent, if the number of its occurrences is not less than number of occurrences of any other substring.

You are given a set of strings. A string (not necessarily from this set) is called good if all elements of the set are the most frequent substrings of this string. Restore the non-empty good string with minimum length. If several such strings exist, restore lexicographically minimum string. If there are no good strings, print "NO" (without quotes).

A substring of a string is a contiguous subsequence of letters in the string. For example, "ab", "c", "abc" are substrings of string "abc", while "ac" is not a substring of that string.

The number of occurrences of a substring in a string is the number of starting positions in the string where the substring occurs. These occurrences could overlap.

String a is lexicographically smaller than string b, if a is a prefix of b, or a has a smaller letter at the first position where a and b differ.


-----Input-----

The first line contains integer n (1 ≤ n ≤ 10^5) — the number of strings in the set.

Each of the next n lines contains a non-empty string consisting of lowercase English letters. It is guaranteed that the strings are distinct.

The total length of the strings doesn't exceed 10^5.


-----Output-----

Print the non-empty good string with minimum length. If several good strings exist, print lexicographically minimum among them. Print "NO" (without quotes) if there are no good strings.


-----Examples-----
Input
4
mail
ai
lru
cf

Output
cfmailru

Input
3
kek
preceq
cheburek

Output
NO



-----Note-----

One can show that in the first sample only two good strings with minimum length exist: "cfmailru" and "mailrucf". The first string is lexicographically minimum.

Difficulty: MEDIUM

Starter code:

Solutions:
def is_all_used(used):
	for val in used.values():
		if val != True:
			return False
	return True

def is_circle(d, pre):
	used = {x: False for x in d}
	pre_none = [x for x in used if x not in pre]
	s_arr = []
	for x in pre_none:
		cur = []
		flg = dfs(x, d, used, cur)
		if flg == True:
			return (True, None)
		s_arr.append(cur)
	if is_all_used(used) != True:
		return (True, None)
	return (False, s_arr)

def dfs(u, d, used, cur):
	used[u] = True
	cur.append(u)
	flg = False
	for v in d[u]:
		if used[v] == True:
			return True
		flg = dfs(v, d, used, cur)
		if flg == True:
			return flg
	return flg

def push(d, u, v=None):
	if u not in d:
		d[u] = set()
	if v is not None:
		if v not in d:
			d[v] = set()
		d[u].add(v)

def push_p(d, v):
	if v not in d:
		d[v] = 0
	d[v] += 1

def is_deg_valid(d):
	for u in d:
		if len(d[u]) > 1:
			return True
	return False

def solve():
	n = int(input())
	d = {}
	pre = {}
	for _ in range(n):
		s = input()
		if len(s) == 1:
			push(d, s)
		else:
			for (u, v) in zip(s[:-1], s[1:]):
				push(d, u, v)
				push_p(pre, v)
	(flg, arr) = is_circle(d, pre)
	if is_deg_valid(d) or flg == True:
		return 'NO'
	S = [''.join(x) for x in arr]
	S = sorted(S)
	return ''.join([s for s in S])
print(solve())


(u, v, d) = ({}, {}, set())
for i in range(int(input())):
	t = input()
	if len(t) == 1:
		d.add(t)
	for (a, b) in zip(t, t[1:]):
		if u.get(a, b) != b or v.get(b, a) != a:
			print('NO')
			return
		(u[a], v[b]) = (b, a)
(x, y) = (set(u), set(v))
d = d - x - y
for q in x - y:
	while q[-1] in u:
		q += u.pop(q[-1])
	d.add(q)
if u:
	print('NO')
	return
print(''.join(sorted(d)))


import math
import random
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
import threading
from collections import defaultdict
threading.stack_size(10 ** 8)
mod = 10 ** 9 + 7
mod1 = 998244353
import os
import sys
from io import BytesIO, IOBase
sys.setrecursionlimit(300000)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class TreeNode:

	def __init__(self, k, v):
		self.key = k
		self.value = v
		self.left = None
		self.right = None
		self.parent = None
		self.height = 1
		self.num_left = 1
		self.num_total = 1

class AvlTree:

	def __init__(self):
		self._tree = None

	def add(self, k, v):
		if not self._tree:
			self._tree = TreeNode(k, v)
			return
		node = self._add(k, v)
		if node:
			self._rebalance(node)

	def _add(self, k, v):
		node = self._tree
		while node:
			if k < node.key:
				if node.left:
					node = node.left
				else:
					node.left = TreeNode(k, v)
					node.left.parent = node
					return node.left
			elif node.key < k:
				if node.right:
					node = node.right
				else:
					node.right = TreeNode(k, v)
					node.right.parent = node
					return node.right
			else:
				node.value = v
				return

	@staticmethod
	def get_height(x):
		return x.height if x else 0

	@staticmethod
	def get_num_total(x):
		return x.num_total if x else 0

	def _rebalance(self, node):
		n = node
		while n:
			lh = self.get_height(n.left)
			rh = self.get_height(n.right)
			n.height = max(lh, rh) + 1
			balance_factor = lh - rh
			n.num_total = 1 + self.get_num_total(n.left) + self.get_num_total(n.right)
			n.num_left = 1 + self.get_num_total(n.left)
			if balance_factor > 1:
				if self.get_height(n.left.left) < self.get_height(n.left.right):
					self._rotate_left(n.left)
				self._rotate_right(n)
			elif balance_factor < -1:
				if self.get_height(n.right.right) < self.get_height(n.right.left):
					self._rotate_right(n.right)
				self._rotate_left(n)
			else:
				n = n.parent

	def _remove_one(self, node):
		replacement = node.left or node.right
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = replacement
			else:
				node.parent.right = replacement
			replacement.parent = node.parent
			node.parent = None
		else:
			self._tree = replacement
			replacement.parent = None
		node.left = None
		node.right = None
		node.parent = None
		self._rebalance(replacement)

	def _remove_leaf(self, node):
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = None
			else:
				node.parent.right = None
			self._rebalance(node.parent)
		else:
			self._tree = None
		node.parent = None
		node.left = None
		node.right = None

	def remove(self, k):
		node = self._get_node(k)
		if not node:
			return
		if AvlTree._is_leaf(node):
			self._remove_leaf(node)
			return
		if node.left and node.right:
			nxt = AvlTree._get_next(node)
			node.key = nxt.key
			node.value = nxt.value
			if self._is_leaf(nxt):
				self._remove_leaf(nxt)
			else:
				self._remove_one(nxt)
			self._rebalance(node)
		else:
			self._remove_one(node)

	def get(self, k):
		node = self._get_node(k)
		return node.value if node else -1

	def _get_node(self, k):
		if not self._tree:
			return None
		node = self._tree
		while node:
			if k < node.key:
				node = node.left
			elif node.key < k:
				node = node.right
			else:
				return node
		return None

	def get_at(self, pos):
		x = pos + 1
		node = self._tree
		while node:
			if x < node.num_left:
				node = node.left
			elif node.num_left < x:
				x -= node.num_left
				node = node.right
			else:
				return (node.key, node.value)
		raise IndexError('Out of ranges')

	@staticmethod
	def _is_left(node):
		return node.parent.left and node.parent.left == node

	@staticmethod
	def _is_leaf(node):
		return node.left is None and node.right is None

	def _rotate_right(self, node):
		if not node.parent:
			self._tree = node.left
			node.left.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.left
			node.left.parent = node.parent
		else:
			node.parent.right = node.left
			node.left.parent = node.parent
		bk = node.left.right
		node.left.right = node
		node.parent = node.left
		node.left = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	def _rotate_left(self, node):
		if not node.parent:
			self._tree = node.right
			node.right.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.right
			node.right.parent = node.parent
		else:
			node.parent.right = node.right
			node.right.parent = node.parent
		bk = node.right.left
		node.right.left = node
		node.parent = node.right
		node.right = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	@staticmethod
	def _get_next(node):
		if not node.right:
			return node.parent
		n = node.right
		while n.left:
			n = n.left
		return n

class SegmentTree1:

	def __init__(self, data, default=2 ** 51, func=lambda a, b: a & b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD

def powm(a, n, m):
	if a == 1 or n == 0:
		return 1
	if n % 2 == 0:
		s = powm(a, n // 2, m)
		return s * s % m
	else:
		return a * powm(a, n - 1, m) % m

def sort_list(list1, list2):
	zipped_pairs = zip(list2, list1)
	z = [x for (_, x) in sorted(zipped_pairs)]
	return z

def product(l):
	por = 1
	for i in range(len(l)):
		por *= l[i]
	return por

def binarySearchCount(arr, n, key):
	left = 0
	right = n - 1
	count = 0
	while left <= right:
		mid = int((right + left) / 2)
		if arr[mid] < key:
			count = mid + 1
			left = mid + 1
		else:
			right = mid - 1
	return count

def countdig(n):
	c = 0
	while n > 0:
		n //= 10
		c += 1
	return c

def binary(x, length):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

def countGreater(arr, n, k):
	l = 0
	r = n - 1
	leftGreater = n
	while l <= r:
		m = int(l + (r - l) / 2)
		if arr[m] >= k:
			leftGreater = m
			r = m - 1
		else:
			l = m + 1
	return n - leftGreater
n = int(input())
l1 = []
l2 = []
for i in range(n):
	s1 = input()
	s = list(s1)
	if len(set(s)) < len(s):
		print('NO')
		sys.exit(0)
	l1.append(s)
	l2.append(s1)
l = [''] * 26
r = [''] * 26
pr = [0] * 26
for i in range(n):
	s = l1[i]
	if len(s) == 1:
		pr[ord(s[0]) - 97] = 1
		continue
	for j in range(len(s)):
		pr[ord(s[j]) - 97] = 1
		if j == 0:
			if r[ord(s[j]) - 97] == '':
				r[ord(s[j]) - 97] = s[j + 1]
			elif r[ord(s[j]) - 97] != s[j + 1]:
				print('NO')
				sys.exit(0)
		elif j == len(s) - 1:
			if l[ord(s[j]) - 97] == '':
				l[ord(s[j]) - 97] = s[j - 1]
			elif l[ord(s[j]) - 97] != s[j - 1]:
				print('NO')
				sys.exit(0)
		else:
			if r[ord(s[j]) - 97] == '':
				r[ord(s[j]) - 97] = s[j + 1]
			elif r[ord(s[j]) - 97] != s[j + 1]:
				print('NO')
				sys.exit(0)
			if l[ord(s[j]) - 97] == '':
				l[ord(s[j]) - 97] = s[j - 1]
			elif l[ord(s[j]) - 97] != s[j - 1]:
				print('NO')
				sys.exit(0)
ans = ''
st = 0
f = 1
for i in range(26):
	if l[i] == '' and pr[i] == 1:
		f = 0
		break
if f == 1:
	print('NO')
	sys.exit(0)
for i in range(26):
	if l[i] == '' and pr[i] == 1:
		st = i
		ans += chr(st + 97)
		while r[st] != '':
			pr[st] = 0
			st = ord(r[st]) - 97
			ans += chr(st + 97)
for i in range(n):
	if l2[i] not in ans:
		print('NO')
		sys.exit(0)
print(ans)


n = int(input())
wrong_str = False
strings = []
sets = []
for _ in range(n):
	new_string = input()
	new_string_set = set(new_string)
	if len(new_string) != len(new_string_set):
		wrong_str = True
		break
	strings.append(new_string)
	sets.append(new_string_set)
if wrong_str:
	print('NO')
	return
connections = []
for _ in range(n):
	connections.append((-1, -1))
changed = True
while changed:
	changed = False
	for i in range(len(strings)):
		if strings[i] == None:
			continue
		for j in range(i + 1, len(strings)):
			if strings[j] == None:
				continue
			if len(set(strings[i]).intersection(set(strings[j]))) == 0:
				continue
			a = strings[i]
			b = strings[j]
			if b in a:
				strings[j] = None
				changed = True
			elif a in b:
				strings[i] = b
				strings[j] = None
				changed = True
			else:
				is_ok = False
				start_index = a.find(b[0])
				if start_index != -1 and a[start_index:] in b:
					strings[i] += strings[j][len(a) - start_index:]
					strings[j] = None
					is_ok = True
					changed = True
				if not is_ok:
					start_index = b.find(a[0])
					if start_index != -1 and b[start_index:] in a:
						strings[i] = strings[j] + strings[i][len(b) - start_index:]
						strings[j] = None
						is_ok = True
						changed = True
				if not is_ok:
					print('NO')
					return
		if wrong_str:
			print('NO')
			return
	strings = [x for x in strings if x is not None]
whole_str = ''.join(strings)
if len(whole_str) != len(set(whole_str)):
	print('NO')
	return
print(''.join(sorted(strings)))


StringsNumber = int(input())
FinalStrings = []
Strings = []
for i in range(StringsNumber):
	Strings.append(input())
LetterGraph = {}
for i in range(len(Strings)):
	if len(Strings[i]) == 1:
		if Strings[i] not in LetterGraph:
			LetterGraph[Strings[i]] = ''
		continue
	for e in range(len(Strings[i]) - 1):
		if Strings[i][e] not in LetterGraph:
			Elements = []
			for j in list(LetterGraph):
				if j != Strings[i][e + 1]:
					Elements.append(LetterGraph[j])
			if Strings[i][e + 1] in Elements:
				print('NO')
				return
			LetterGraph[Strings[i][e]] = Strings[i][e + 1]
			continue
		if LetterGraph[Strings[i][e]] == Strings[i][e + 1] or LetterGraph[Strings[i][e]] == '':
			LetterGraph[Strings[i][e]] = Strings[i][e + 1]
			continue
		print('NO')
		return
if LetterGraph:
	Cycle = False
	for i in LetterGraph:
		Letter = LetterGraph[i]
		while True:
			if Letter in LetterGraph:
				if LetterGraph[Letter] == i:
					print('NO')
					return
				Letter = LetterGraph[Letter]
			else:
				break
if LetterGraph:
	IsIFirstSymbol = False
	FirstSymbols = []
	for i in LetterGraph:
		IsIFirstSymbol = True
		for e in LetterGraph:
			if LetterGraph[e] == i:
				IsIFirstSymbol = False
		if IsIFirstSymbol:
			FirstSymbols.append(i)
	if not FirstSymbols:
		print('NO')
		return
if LetterGraph:
	Letter = ''
	for i in FirstSymbols:
		FinalString = i
		Letter = i
		for e in range(len(LetterGraph)):
			if Letter in LetterGraph:
				if not LetterGraph[Letter] == '':
					FinalString += LetterGraph[Letter]
					Letter = LetterGraph[Letter]
				else:
					break
			else:
				break
		FinalStrings.append(FinalString)
FinalStrings.sort()
RESULT = ''
for i in FinalStrings:
	RESULT += i
print(RESULT)


n = int(input())
A = []
for i in range(0, n):
	A = A + [input()]
start = [100] * 26
end = [100] * 26

def num(x):
	return ord(x) - ord('a')

def let(x):
	return chr(x + ord('a'))

def ans(x):
	final = []
	for i in range(0, n):
		B = list(A[i])
		if len(B) == 1:
			if start[num(B[0])] == 100:
				start[num(B[0])] = -100
			if end[num(B[0])] == 100:
				end[num(B[0])] = -100
		else:
			for j in range(0, len(B)):
				if j == 0:
					if start[num(B[j])] == 100 or start[num(B[j])] == -100:
						start[num(B[j])] = -100
					if end[num(B[j])] == 100 or end[num(B[j])] == -100:
						end[num(B[j])] = num(B[j + 1])
					elif end[num(B[j])] == num(B[j + 1]):
						g = 0
					else:
						return 'NO'
				elif 0 < j < len(B) - 1:
					if start[num(B[j])] == 100 or start[num(B[j])] == -100:
						start[num(B[j])] = num(B[j - 1])
					elif start[num(B[j])] != num(B[j - 1]):
						return 'NO'
					if end[num(B[j])] == 100 or end[num(B[j])] == -100:
						end[num(B[j])] = num(B[j + 1])
					elif end[num(B[j])] != num(B[j + 1]):
						return 'NO'
				elif j == len(B) - 1:
					if end[num(B[j])] == 100:
						end[num(B[j])] = -100
					if start[num(B[j])] == 100 or start[num(B[j])] == -100:
						start[num(B[j])] = num(B[j - 1])
					elif start[num(B[j])] == num(B[j - 1]):
						g = 0
					else:
						return 'NO'
	if len(set(start)) + max(0, start.count(100) - 1) + max(0, start.count(-100) - 1) != 26:
		return 'NO'
	elif len(set(end)) + max(0, end.count(100) - 1) + max(0, end.count(-100) - 1) != 26:
		return 'NO'
	else:
		for i in range(0, 26):
			if start[i] != -100:
				g = 0
			else:
				final = final + [let(i)]
				j = end[i]
				while j != -100:
					final = final + [let(j)]
					j = end[j]
		if len(final) != len(set(start)) - min(1, start.count(100)) + max(0, start.count(-100) - 1):
			return 'NO'
		else:
			return ''.join(final)
print(ans(A))


L = {}
R = {}
S = set()
for _ in range(int(input())):
	s = input()
	if len(s) == 1:
		S.add(s)
	for (s1, s2) in zip(s, s[1:]):
		if s2 != L.get(s1, s2) or s1 != R.get(s2, s1):
			print('NO')
			return
		(L[s1], R[s2]) = (s2, s1)
(L1, R1) = (set(L), set(R))
S = S - L1 - R1
for i in L1 - R1:
	while i[-1] in L:
		i += L.pop(i[-1])
	S.add(i)
if L:
	print('NO')
	return
print(''.join(sorted(S)))


n = int(input())
m = []
sc = []
for i in range(n):
	m.append(input())
	sc.append(set(m[i]))
	if len(sc[i]) != len(m[i]):
		print('NO')
		break
else:
	i = 0
	pX = False
	while i < len(m):
		j = i + 1
		p = False
		while j < len(m):
			z = len(sc[i].intersection(sc[j]))
			if m[i] in m[j]:
				m[i] = m[j]
				sc[i] = sc[j]
				sc.pop(j)
				m.pop(j)
				p = True
				break
			elif m[j] in m[i]:
				sc.pop(j)
				m.pop(j)
				j -= 1
			elif z > 0:
				if m[i][-z:] == m[j][:z]:
					m[i] += m[j][z:]
				elif m[j][-z:] == m[i][:z]:
					m[i] = m[j] + m[i][z:]
				else:
					pX = True
					break
				sc[i] = set(m[i])
				m.pop(j)
				sc.pop(j)
				j -= 1
				p = True
			j += 1
		if not p:
			i += 1
		if pX:
			print('NO')
			break
	if not pX:
		print(''.join(sorted(m)))


def generate_good_string(subs: list):
	(In, Out, S) = ({}, {}, set())
	for s in subs:
		if len(s) == 1:
			S.add(s)
		for (fr, to) in zip(s, s[1:]):
			if fr != In.get(to, fr) or to != Out.get(fr, to):
				return print('NO')
			(Out[fr], In[to]) = (to, fr)
	(Outset, Inset) = (set(Out), set(In))
	S -= set.union(Outset, Inset)
	for s in Outset - Inset:
		while Out.get(s[-1]):
			s += Out.pop(s[-1])
		S.add(s)
	print('NO' if Out else ''.join(sorted(S)))
substrings = [input() for _ in range(int(input()))]
generate_good_string(substrings)


from sys import exit
n = int(input())
letters_prev = [None for i in range(30)]
letters_fow = [None for i in range(30)]
okk = [False for i in range(30)]
for i in range(n):
	task = [ord(i) - ord('a') for i in input()]
	if len(task) == 1:
		okk[task[0]] = True
	for i in range(1, len(task)):
		if letters_prev[task[i]] is not None and letters_prev[task[i]] != task[i - 1] or task[i] == task[i - 1]:
			print('NO')
			exit()
		else:
			letters_prev[task[i]] = task[i - 1]
	for i in range(len(task) - 1):
		if letters_fow[task[i]] is not None and letters_fow[task[i]] != task[i + 1] or task[i] == task[i + 1]:
			print('NO')
			exit()
		else:
			letters_fow[task[i]] = task[i + 1]

def chain_p(x, was=[]):
	global letters_fow, letters_prev
	if x is None:
		return []
	if letters_prev[x] is None:
		return [x]
	else:
		if letters_prev[x] in was:
			print('NO')
			exit()
		ans = chain_p(letters_prev[x], was=was + [letters_prev[x]]) + [x]
		return ans

def chain_f(x, was=[]):
	global letters_fow, letters_prev
	if x is None:
		return []
	if letters_fow[x] is None:
		return [x]
	else:
		if letters_fow[x] in was:
			print('NO')
			exit()
		ans = chain_f(letters_fow[x], was=was + [letters_fow[x]]) + [x]
		return ans
done = []
cc = []
while True:
	flag = False
	for i in range(30):
		if i in done:
			continue
		prev = []
		post = []
		if letters_prev[i] is not None:
			flag = True
			prev = chain_p(letters_prev[i])
		if letters_fow[i] is not None:
			flag = True
			post = chain_f(letters_fow[i])
		done.extend(prev)
		done.extend(post)
		done.append(i)
		if len(prev) + len(post) == 0 and okk[i]:
			cc.append(chr(i + ord('a')))
		elif len(prev) + len(post) > 0:
			cc.append(''.join([chr(i + ord('a')) for i in prev] + [chr(i + ord('a'))] + [chr(i + ord('a')) for i in post][::-1]))
	if not flag:
		break
cc.sort()
print(''.join(cc))


n = int(input())
u = []
s = []
ok = True
for i in range(n):
	u.append(input())
	s.append(set(u[i]))
	if len(s[i]) != len(u[i]):
		print('NO')
		ok = False
		break
if ok:
	i = 0
	ok = False
	while i < len(u):
		j = i + 1
		p = False
		while j < len(u):
			z = len(s[i].intersection(s[j]))
			if u[i] in u[j]:
				u[i] = u[j]
				s[i] = s[j]
				s.pop(j)
				u.pop(j)
				p = True
				break
			elif u[j] in u[i]:
				s.pop(j)
				u.pop(j)
				j -= 1
			elif z > 0:
				if u[i][-z:] == u[j][:z]:
					u[i] += u[j][z:]
				elif u[j][-z:] == u[i][:z]:
					u[i] = u[j] + u[i][z:]
				else:
					ok = True
					break
				s[i] = set(u[i])
				u.pop(j)
				s.pop(j)
				j -= 1
				p = True
			j += 1
		if not p:
			i += 1
		if ok:
			print('NO')
			break
	if not ok:
		u.sort()
		print(''.join(u))