Problem Statement

We found a dictionary of the Ancient Civilization Mayo (ACM) during excavation of the ruins. After analysis of the dictionary, we revealed they used a language that had not more than 26 letters. So one of us mapped each letter to a different English alphabet and typed all the words in the dictionary into a computer.

How the words are ordered in the dictionary, especially whether they are ordered lexicographically, is an interesting topic to many people. As a good programmer, you are requested to write a program to judge whether we can consider the words to be sorted in a lexicographical order.

Note: In a lexicographical order, a word always precedes other words it is a prefix of. For example, `ab` precedes `abc`, `abde`, and so on.



Input

The input consists of multiple datasets. Each dataset is formatted as follows:


n
string_1
...
string_n


Each dataset consists of n+1 lines. The first line of each dataset contains an integer that indicates n (1 \leq n \leq 500). The i-th line of the following n lines contains string_i, which consists of up to 10 English lowercase letters.

The end of the input is `0`, and this should not be processed.

Output

Print either `yes` or `no` in a line for each dataset, in the order of the input. If all words in the dataset can be considered to be ordered lexicographically, print `yes`. Otherwise, print `no`.

Example

Input

4
cba
cab
b
a
3
bca
ab
a
5
abc
acb
b
c
c
5
abc
acb
c
b
b
0


Output

yes
no
yes
no
/* monkukui 競技プログラミング用のテンプレート  (ここから) */
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <functional>
#include <bitset>

using namespace std;
using lint = long long int;
using ll = long long int;
using lnt = long long int;
using graph = vector<vector<int>>;
using wgraph = vector<vector<pair<int, long long int>>>;
long long int INF = 1001001001001001LL;
int inf = 100100100;
long long int MOD = 1000000007LL;
double PI = 3.1415926535897932;
long long int di[] = {-1, 0, 1, 0, -1, 1, 1, -1};
long long int dj[] = {0, 1, 0, -1, 1, 1, -1, -1};

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

#define rep(i,n) for(int i = 0; i < (n); i++)
#define rrep(i,n) for(int i = 1; i <= (n); i++)
#define drep(i,n) for(int i = (n)-1; i >= 0; i--)
#define srep(i,s,t) for(int i = s; i < t; i++)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define pb push_back

/* monkukui 競技プログラミング用のテンプレート (ここまで)*/

struct StronglyConnectedComponents {
public:
  const int n;
  vector<bool> isthrough;
  vector<int> vs, cmp;
  vector< vector<int> > G, rG, H; // グラフ、逆辺グラフ、縮約後のグラフ

  StronglyConnectedComponents(vector<vector<int>> &g) :
    n(g.size()), isthrough(n, false), cmp(n, 0), G(n), rG(n) {
    for(int i = 0; i < n; i++) {
      for(size_t j = 0; j < g[i].size(); j++) {
        G[i].push_back(g[i][j]);
        rG[g[i][j]].push_back(i);
      }
    }
  }

  void SccDfsOne(int cur) {
    isthrough[cur] = true;
    for(size_t i = 0; i < G[cur].size(); i++) {
      if(!isthrough[G[cur][i]]) {
        SccDfsOne(G[cur][i]);
      }
    }
    vs.push_back(cur);
  }

  void SccDfsTwo(vector<int> &vec, int cur, int k) {
    cmp[cur] = k;
    isthrough[cur] = true;
    vec.push_back(cur);
    for(size_t i = 0; i < rG[cur].size(); i++) {
      if(!isthrough[rG[cur][i]]) {
        SccDfsTwo(vec, rG[cur][i], k);
      }
    }
  }

  // 縮約後のグループ、グループ数
  pair<vector<int>, int> scc() {
    // 1回めのDFS
    for(int i = 0; i < n; i++)
      if(!isthrough[i]) SccDfsOne(i);

    fill(isthrough.begin(), isthrough.end(), false);
    reverse(vs.begin(), vs.end());
    int k = 0; vector<vector<int>> S;

    // 2回めのDFS
    for(size_t i = 0; i < vs.size(); i++) {
      if(!isthrough[vs[i]]) {
        S.push_back(vector<int>());
        SccDfsTwo(S.back(), vs[i], k++);
      }
    }

    H.resize(k);
    fill(isthrough.begin(), isthrough.end(), false);
    for(size_t i = 0; i < k; i++) {
      for(size_t j = 0; j < S[i].size(); j++) {
        int v = S[i][j];
        for(size_t x = 0; x < G[v].size(); x++) {
          int u = G[v][x];
          if(isthrough[cmp[u]] or cmp[v] == cmp[u]) continue;
          isthrough[cmp[u]] = true;
          H[cmp[v]].push_back(cmp[u]);
        }
      }
      for(size_t j=0; j<H[i].size(); j++) isthrough[H[i][j]] = false;
    }
    return make_pair(cmp, k);
  }
};

// 閉路があるか
bool func(graph g) {
  
  StronglyConnectedComponents scc(g);
  auto hoge = scc.scc();
  return (hoge.second != g.size());
  return false;
}

int main(){
  
  while(1) {
    int n; cin >> n;
    if(n == 0) break;
    vector<string> vs(n);
    for(int i = 0; i < n; i++) {
      cin >> vs[i];
      vs[i] = vs[i] + '#';
    }

    graph g(26);

    bool flag = false;
    for(int i = 0; i < n; i++) {
      for(int j = i + 1; j < n; j++) {
        int u = -1;
        int v = -1;
        if(vs[i] == vs[j]) continue;

        for(int k = 0; k < min(vs[i].size(), vs[j].size()); k++) {
          if(vs[i][k] == vs[j][k]) continue;

          // 不一致
          if(vs[i][k] == '#') continue;
          if(vs[j][k] == '#') {
            cout << "no" << endl;
            i += n;
            j += n;
            flag = true;
            break;
          }

          u = vs[i][k] - 'a';
          v = vs[j][k] - 'a';

          // u -> v
          g[u].push_back(v);
          break;
        }
      }
    }

    if(flag) continue;

    if(func(g)) cout << "no" << endl;
    else        cout << "yes" << endl;

  }
  return 0;
}

