#include<bits/stdc++.h>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define FZ(n) memset((n),0,sizeof(n))
#define FMO(n) memset((n),-1,sizeof(n))
#define MC(n,m) memcpy((n),(m),sizeof(n))
#define F first
#define S second
#define MP make_pair
#define PB push_back
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
    freopen(name".in", "r", stdin); \
    freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif
// Let's Fight!

const int MAXN = 777;
const int MAXS = 10101010;

int N;
string s[MAXN];
int V;
vector<int> vals[MAXN];
int vis[MAXN];
bool edge[MAXN][MAXN];
bool isans[MAXN];

class ACautomata{
	public:
	class Node{
		public:
		int vno;
		Node *go[2], *fail, *dfail;
		Node (){
      vno = -1;
			memset(go,0,sizeof(go));
			fail = 0;
      dfail = 0;
		}
	};

	Node *root, pool[MAXS];
	int nMem;

	Node* new_Node(){
		pool[nMem] = Node();
		return &pool[nMem++];
	}
	void init(){
		nMem = 0;
		root = new_Node();
	}
	void add(const string &str, int val){
		insert(root,str,0,val);
	}
	void insert(Node *cur, const string &str, int pos, int val){
		if (pos >= (int)str.size()){
      if(cur->vno == -1)
      {
        vis[V] = -1;
        cur->vno = V++;
      }
      vals[cur->vno].PB(val);
			return;
		}
		int c = str[pos]-'a';
		if (cur->go[c] == 0){
			cur->go[c] = new_Node();
		}
		insert(cur->go[c],str,pos+1,val);
	}

	void make_fail(){
		queue<Node*> que;
		que.push(root);
		while (!que.empty()){
			Node* fr=que.front();
			que.pop();
			for (int i=0; i<2; i++){
				if (fr->go[i]){
					Node *ptr = fr->fail;
					while (ptr && !ptr->go[i])
						ptr = ptr->fail;
					if (!ptr)
						fr->go[i]->fail = root;
					else
						fr->go[i]->fail = ptr->go[i];
					que.push(fr->go[i]);
				}
			}
		}
	}

  Node* calc_dfail(Node *n)
  {
    if(n->dfail) return n->dfail;
    if(n == root)
      n->dfail = root;
    else
    {
      Node *f = n->fail;
      if(f->vno != -1)
        n->dfail = f;
      else
        n->dfail = calc_dfail(f);
    }
    return n->dfail;
  }

  void make_dfail()
  {
    for(int i=0; i<nMem; i++)
      calc_dfail(&pool[i]);
  }

  Node* step(Node* n, char c)
  {
    int x = c - 'a';
    while(1)
    {
      if(n->go[x])
        return n->go[x];
      if(n == root)
        break;
      n = n->fail;
    }
    return n;
  }
} ac;

class Isap{
public:
	static const int MXN = MAXN*2;
  class Edge{
  public:
    int v,f,re;
    Edge (){ v=f=re=-1; }
    Edge (int _v, int _f, int _r){
      v = _v;
      f = _f;
      re = _r;
    }
  };
  int n,s,t,h[MXN],gap[MXN];
  bool reach[MXN];
  vector<Edge> E[MXN];
  void init(int _n, int _s, int _t){
    n = _n;
    s = _s;
    t = _t;
    for (int i=0; i<n; i++)
    {
      E[i].clear();
      reach[i] = false;
    }
  }
  void add_edge(int u, int v, int f){
    E[u].PB(Edge(v,f,E[v].size()));
    E[v].PB(Edge(u,0,E[u].size()-1));
  }
  int DFS(int u, int nf, int res=0){
    if (u == t) return nf;
    for (auto &it : E[u]){
      if (h[u]==h[it.v]+1 && it.f>0){
        int tf = DFS(it.v,min(nf,it.f));
        res += tf;
        nf -= tf;
        it.f -= tf;
        E[it.v][it.re].f += tf;
        if (nf == 0) return res;
      }
    }
    if (nf){
      if (--gap[h[u]] == 0) h[s]=n;
      gap[++h[u]]++;
    }
    return res;
  }
  int flow(int res=0){
    FZ(h);
    FZ(gap);
    gap[0] = n;
    while (h[s] < n)
      res += DFS(s,2147483647);
    return res;
  }
  void reach_dfs(int v)
  {
    if(reach[v]) return;
    reach[v] = true;
    for(auto e: E[v])
    {
      if(e.f == 0) continue;
      reach_dfs(e.v);
    }
  }
}flow;

void link(int a, int b)
{
  if(a == b) return;
  if(s[a].size() > s[b].size())
    swap(a, b);
  if(s[a].size() == s[b].size() && a > b)
    swap(a, b);
  edge[a][b] = true;
}

void build_edge()
{
  ac.init();
  for(int i=0; i<N; i++)
    ac.add(s[i], i);
  ac.make_fail();
  ac.make_dfail();

  for(int i=0; i<N; i++)
  {
    auto n = ac.root;
    for(auto c: s[i])
    {
      n = ac.step(n, c);
      auto p = n;
      while(p != ac.root)
      {
        if(p->vno != -1)
        {
          int v = p->vno;
          if(vis[v] != i)
          {
            vis[v] = i;
            for(auto x: vals[v])
              link(x, i);
          }
          else
            break;
        }
        p = p->dfail;
      }
    }
  }
}

vector<int> calc()
{
  vector<int> ret;

  int S = 2*N, T = 2*N+1;
  flow.init(2*N+2, S, T);
  for(int i=0; i<N; i++)
  {
    flow.add_edge(S, i, 1);
    flow.add_edge(N+i, T, 1);
  }
  for(int i=0; i<N; i++)
    for(int j=0; j<N; j++)
      if(edge[i][j])
        flow.add_edge(i, N+j, 1);

  flow.flow();
  flow.reach_dfs(S);

  for(int i=0; i<N; i++)
    isans[i] = true;
  for(int i=0; i<N; i++)
    if(!flow.reach[i] || flow.reach[N+i])
      isans[i] = false;
  for(int i=0; i<N; i++)
    if(isans[i])
      ret.PB(i);

  return ret;
}

int main()
{
  IOS;
  cin>>N;
  for(int i=0; i<N; i++)
    cin>>s[i];

  build_edge();
  vector<int> ans = calc();

  cout<<ans.size()<<endl;
  for(auto v: ans)
    cout<<v+1<<" ";
  cout<<endl;

  return 0;
}

// ntuj - eopgwp544iox98o22d52b


#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
const int C=2;
struct AC_auto {
	char base;
    struct node{
        int next[C],fail,cnt,go;
        std::vector<int> *ids;
        node():fail(-1),cnt(0),ids(0){
            for(int i=0;i<C;i++) next[i]=0;
        }
    };
    std::vector<node> V;
    AC_auto():V(1),base('a'){};
    inline void clear(){
        V.clear();
        V.push_back(node());
    }
    inline void insert(char *s,int id){
        int now=0;
        for(int i=0;s[i];i++){
            int c=s[i]-base;
            if(V[now].next[c]==0){
                V.push_back(node());
                V[now].next[c]=V.size()-1;
            }
            now=V[now].next[c];
        }
        V[now].cnt++;
        if(!V[now].ids) V[now].ids = new std::vector<int>;
        V[now].ids->push_back(id);
    }
    inline void build_fail(){
        std::queue<int> Q;
        Q.push(0);
        V[0].go=0;
        while(!Q.empty()){
            int now=Q.front();
            Q.pop();
            if(now){if(V[V[now].fail].cnt) V[now].go=V[now].fail;
            else V[now].go=V[V[now].fail].go;}
            //printf("%d %d %d %d\n",now,V[0].go,V[now].fail,V[V[now].fail].cnt);
            for(int i=0;i<C;i++){
                if(V[now].next[i]==0) continue;
                int pfail=V[now].fail;
                while(pfail!=-1&&V[pfail].next[i]==0) pfail=V[pfail].fail;
                V[V[now].next[i]].fail=pfail==-1 ? 0:V[pfail].next[i];
                Q.push(V[now].next[i]);
            }
        }
    }
    inline int solve(char *t,int *res){
        int i,now=0,x,r=0;
        for(i=0;t[i];i++){
            int c=t[i]-base;
            while(now>0&&V[now].next[c]==0) now=V[now].fail;
            if(V[now].next[c]==0) continue;
            x=now=V[now].next[c];
            while(x>0){
                if(V[x].ids)for(int j=0;j<V[x].ids->size();j++){
                	//if(res[V[x].ids[j]]) goto end; //cut
                    res[V[x].ids->at(j)]=1;
                }
                //printf("%d %d\n",x,V[x].go);
                x=V[x].go;

                //x=V[x].fail;
            }
            //now=x;
            //end:;
        }
        return r;
    }
} ac;
struct Perfect_graph {
	int (*adj)[750],n; // NEED SET IT!!
	int used[2][750],matched[750],mx[750];
	void tracking(int u) {
	    if (used[0][u]) return ;
	    used[0][u] = true;
	    for(int v=0;v<n;v++){
			if (adj[u][v]&&!used[1][v]) {
			    used[1][v] = true;
				if(mx[v]!=-1) tracking(mx[v]);
			}
	    }
	}
	bool matching(int u) {
	    for(int v=0;v<n;v++){
	        if (adj[u][v]&&!used[0][v]) {
	        	used[0][v] = true;
	            if (mx[v] == -1 || matching(mx[v])) {
	                mx[v] = u;
	                return true;
	            }
	        }
	    }
	    return false;
	}
	std::vector<int> maximum_independent_set_find(){
		std::vector<int> ans;
		for(int i=0;i<n;i++){
			mx[i]=-1;
		}
		for(int i=0;i<n;i++){ // or i=0 ?
			for(int j=0;j<n;j++){
				used[0][j] = false;
			}
	        matched[i] = matching(i);
	    }
	    for(int i=0;i<n;i++){
	    	used[0][i] = used[1][i] = false;
	    }
	    for(int i=0;i<n;i++){
	        if (!matched[i]) tracking(i);
	    }
	    for(int i=0;i<n;i++){
	        if (!(matched[i] && !used[0][i] || mx[i] != -1 && used[1][i]))
	            ans.push_back(i);
	    }
	    return ans;
	}
} perfect_graph;
char s_p[10000000 + 750];
char *s[750], *s_pnow;
int r[750][750];
int main(){
	int i,j,k;
	int n;
	scanf("%d",&n);
	//n=100;
	s_pnow = s_p;
	for(i=0;i<n;i++){
		s[i]=s_pnow;
	//	for(j=0;j<=100000;j++) s[i][j]='a';
		//s[i][j]=0;
		//printf("%s\n",s[i]);
		scanf("%s",s[i]);
		while(*s_pnow++);
		ac.insert(s[i],i);
	}
	ac.build_fail();
	//printf("%d\n",ac.V.size());
	for(i=0;i<n;i++){
		ac.solve(s[i],r[i]);
		//printf("%d\n",i);
		r[i][i]=0;
	}
	perfect_graph.n=n;
	perfect_graph.adj=r;
	std::vector<int> ans=perfect_graph.maximum_independent_set_find();
	printf("%d\n",ans.size());
	for(i=0;i<ans.size();i++){
		printf("%d%c",ans[i]+1," \n"[i==n-1]);
	}
}
// 3 a b ab
// 3 a aa ab
// ntuj - 4tgnb22jwsisk99bykawx


#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>          //cout<<fixed<<setprecision(10);
//#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
//#include <memory.h>
#include <cassert>

#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) ((int)strlen(X))
#define F first
#define S second
#define IOS ios_base::sync_with_stdio(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
    freopen(name".in", "r", stdin); \
    freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> ii;
typedef pair<ll,ll> pll;
/*#include<complex>
typedef complex<double> cd;
#define X real()
#define Y imag()*/

int L[800],N;
bitset<800> EE[800];

const int maxn = 1600 + 10;
const int INF = 1000000000;

struct Edge {
  int from, to, cap, flow;
};

bool operator < (const Edge& a, const Edge& b) {
  return a.from < b.from || (a.from == b.from && a.to < b.to);
}

struct ISAP {
  int n, m, s, t;
  vector<Edge> edges;
  vector<int> G[maxn];   //鄰接表，G[i][j]表示節點i的第j條邊在e數組中的序號
  bool vis[maxn];        //BFS使用
  int d[maxn];           //從起點到i的距離
  int cur[maxn];        //當前弧指針
  int p[maxn];          //可增廣路上的一條弧
  int num[maxn];        //距離標號計數

  void AddEdge(int from, int to, int cap) {
    edges.push_back((Edge){from, to, cap, 0});
    edges.push_back((Edge){to, from, 0, 0});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(t);
    vis[t] = 1;
    d[t] = 0;
    while(!Q.empty()) {
      int x = Q.front(); Q.pop();
      for(int i = 0; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]^1];
        if(!vis[e.from] && e.cap > e.flow) {
          vis[e.from] = 1;
          d[e.from] = d[x] + 1;
          Q.push(e.from);
        }
      }
    }
    return vis[s];
  }

  void ClearAll(int n) {
    this->n = n;
    for(int i = 0; i < n; i++){
      G[i].clear();
      d[i]=INF;
    }
    edges.clear();
  }

  void ClearFlow() {
    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
  }

  int Augment() {
    int x = t, a = INF;
    while(x != s) {
      Edge& e = edges[p[x]];
      a = min(a, e.cap-e.flow);
      x = edges[p[x]].from;
    }
    x = t;
    while(x != s) {
      edges[p[x]].flow += a;
      edges[p[x]^1].flow -= a;
      x = edges[p[x]].from;
    }
    return a;
  }

  int Maxflow(int s, int t) {
    this->s = s; this->t = t;
    int flow = 0;
    BFS();
    if(d[s]>=n)return 0;
    memset(num, 0, sizeof(num));
    memset(p, 0, sizeof(p));
    for(int i = 0; i < n; i++)if(d[i]<INF) num[d[i]]++;
    int x = s;
    memset(cur, 0, sizeof(cur));
    while(d[s] < n) {
      if(x == t) {
        flow += Augment();
        x = s;
      }
      int ok = 0;
      for(int i = cur[x]; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]];
        if(e.cap > e.flow && d[x] == d[e.to] + 1) { //Advance
          ok = 1;
          p[e.to] = G[x][i];
          cur[x] = i; //注意
          x = e.to;
          break;
        }
      }
      if(!ok) { //Retreat
        int m = n-1; //初值注意
        for(int i = 0; i < G[x].size(); i++) {
          Edge& e = edges[G[x][i]];
          if(e.cap > e.flow) m = min(m, d[e.to]);
        }
        if(--num[d[x]] == 0) break;
        num[d[x] = m+1]++;
        cur[x] = 0; //注意
        if(x != s) x = edges[p[x]].from;
      }
    }
    return flow;
  }

  vector<int> Mincut() { // call this after maxflow
    BFS();
    vector<int> ans;
    for(int i = 0; i < edges.size(); i++) {
      Edge& e = edges[i];
      if(!vis[e.from] && vis[e.to] && e.cap > 0) ans.push_back(i);
    }
    return ans;
  }

  void Reduce() {
    for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
  }

  void print() {
    printf("Graph:\n");
    for(int i = 0; i < edges.size(); i++)
      printf("%d->%d, %d, %d\n", edges[i].from, edges[i].to , edges[i].cap, edges[i].flow);
  }

  bool reach[maxn];
  void dfs_reach(int x){
    if(reach[x])return;
    reach[x]=true;
    REP(i,0,SZ(G[x])){
        if(edges[G[x][i]].cap)dfs_reach(edges[G[x][i]].to);
    }
  }
}flow;

//const int SIGMA_SIZE = 2;
const int MAXN = 755 ;
const int MAXS = 1e7 + 5 ;

struct Node
{
    Node* nxt[2] ;
    Node* fail ;
    int val ;
} ;

struct AhoCorasickAutomata
{
    Node nodepool[MAXS] , *ntp , *root;
    queue<Node*> q;
    Node* newnode ()
    {
        ntp->nxt[0] = ntp->nxt[1] = ntp->fail = NULL ;
        ntp->val = -1 ;
        return ntp ++ ;
    }

    void init ()
    {
        for ( int i = 0 ; i < N ; ++ i )
        {
            EE[i].reset () ;
        }
        ntp = nodepool ;
        root = newnode () ;
    }

    bool insert ( char s[] , int n , int idx )
    {
        Node* now = root ;
        for ( int i = 0 ; i < n ; ++ i )
        {
            int x = s[i] - 'a' ;
            if ( now->nxt[x] == NULL ) now->nxt[x] = newnode () ;
            now = now->nxt[x] ;
        }
        if ( now->val == -1 ){now->val = idx ;return true;}
        else return false;
    }

    void getFail ()
    {
        root->fail = root ;
        for ( int i = 0 ; i < 2 ; ++ i )
       {
            if ( root->nxt[i] == NULL )
            {
                root->nxt[i] = root ;
            }
            else
            {
                root->nxt[i]->fail = root ;
                q.push(root->nxt[i]) ;
            }
        }
        while ( !q.empty() )
        {
            Node* now = q.front() ;q.pop();
            if ( now->val == -1 ) now->val = now->fail->val ;
            for ( int i = 0 ; i < 2 ; ++ i )
            {
                if ( now->nxt[i] == NULL )
                {
                    now->nxt[i] = now->fail->nxt[i] ;
                }
                else
                {
                    now->nxt[i]->fail = now->fail->nxt[i] ;
                    q.push(now->nxt[i]) ;
                }
            }
        }
    }

    void find ( char s[] , int n , int idx )
    {
        Node* now = root ;
        for ( int i = 0 ; i < n ; ++ i )
        {
            now = now->nxt[s[i] - 'a'] ;
            int x = now->fail->val ;
            int y = now->val ;
            if ( i == n - 1 && x != -1 ) EE[x][idx] = 1 ;
            if ( i <  n - 1 && y != -1 ) EE[y][idx] = 1 ;
        }
    }
} ac;

void floyd ()
{
    for ( int k = 0 ; k < N ; ++ k )
    {
        for ( int i = 0 ; i < N ; ++ i ) if ( EE[i][k] )
            {
                EE[i] |= EE[k] ;
            }
    }
}

char str[10001000];
bitset<800> same;
vector<int> start;

int main()
{
    flow.ClearAll(1600);
    ac.init();
    RI(N);
    int now=0;
    REP(i,0,N){
        RS(str+now);
        start.PB(now);
        L[i]=LEN(str+now);
        if(!ac.insert(str+now,L[i],i))same[i]=1;
        now+=L[i]+1;
    }
    ac.getFail();
    //REP(i,0,SZ(start))cout<<str+start[i]<<endl;
    REP(i,0,N){
        ac.find(str+start[i],L[i],i);
        //puts("");
        if(!same[i]){
            flow.AddEdge(N+N,i,1);
            flow.AddEdge(N+i,N+N+1,1);
        }
    }
    //REP(i,0,N)cout<<EE[i]<<endl;
    floyd();
    REP(i,0,N){
        REP(j,0,N){
            //if(EE[i][j])cout<<i+1<<' '<<j+1<<endl;
            if(EE[i][j]&&L[i]<L[j]){
                flow.AddEdge(i,j+N,1);
            }
        }
    }
    flow.Maxflow(N+N,N+N+1);
    flow.Reduce();
    flow.dfs_reach(N+N);
    vector<int> ans;
    REP(i,0,N){
        //if(flow.edges[i].from==N+N&&flow.edges[i].flow==0)same[flow.edges[i].to]=1;
        //if(flow.edges[i].to==N+N+1&&flow.edges[i].flow==1)same[flow.edges[i].from-N]=1;
        //if(flow.edges[i].from==N+N)cout<<"FROM: "<<flow.edges[i].to<<' '<<flow.edges[i].flow<<endl;
        //if(flow.edges[i].to==N+N+1)cout<<"TO: "<<flow.edges[i].from-N<<' '<<flow.edges[i].flow<<endl;
        if(!flow.reach[i]||flow.reach[i+N])same[i]=1;
    }
    /*REP(i,0,N){
        if(!flow.vis[i]||flow.vis[i+N])same[i]=1;
    }*/
    REP(i,0,N)if(!same[i])ans.PB(i+1);
    printf("%d\n",SZ(ans));
    REP(i,0,SZ(ans))printf("%d ",ans[i]);
    puts("");
    return 0;
}

// ntuj - caidp8ws7l944mrrni1qo


#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
const int C=2;
struct AC_auto {
    char base;
    struct node{
        int next[C],fail,go;
        int id;
        node():fail(-1),id(-1){
            for(int i=0;i<C;i++) next[i]=0;
        }
    };
    std::vector<node> V;
    AC_auto():V(1),base('a'){};
    inline void clear(){
        V.clear();
        V.push_back(node());
    }
    inline void insert(char *s,int id){
        int now=0;
        for(int i=0;s[i];i++){
            int c=s[i]-base;
            if(V[now].next[c]==0){
            	V[now].next[c]=V.size();
                V.push_back(node());
            }
            now=V[now].next[c];
        }
        V[now].id = id;
    }
    inline void build_fail(){
        std::queue<int> Q;
        Q.push(0);
        V[0].go=0;
        while(!Q.empty()){
            int now=Q.front();
            Q.pop();
            if(now){if(V[V[now].fail].id>=0) V[now].go=V[now].fail;
            else V[now].go=V[V[now].fail].go;}
            for(int i=0;i<C;i++){
                if(V[now].next[i]==0) continue;
                int pfail=V[now].fail;
                while(pfail!=-1&&V[pfail].next[i]==0) pfail=V[pfail].fail;
                V[V[now].next[i]].fail=pfail==-1 ? 0:V[pfail].next[i];
                Q.push(V[now].next[i]);
            }
        }
    }
    inline int solve(char *t,int *res){
        int i,now=0,x,r=0;
        for(i=0;t[i];i++){
            int c=t[i]-base;
            while(now>0&&V[now].next[c]==0) now=V[now].fail;
            if(V[now].next[c]==0) continue;
            x=now=V[now].next[c];
            while(x>0){
                if(V[x].id>=0) {
                    if(res[V[x].id]) break;
                    res[V[x].id]++;
                }
                x=V[x].go;
            }
        }
        return r;
    }
} ac;
struct Perfect_graph {
    int (*adj)[750],n; // NEED SET IT!!
    int used[2][750],matched[750],mx[750];
    void tracking(int u) {
        if (used[0][u]) return ;
        used[0][u] = true;
        for(int v=0;v<n;v++){
            if (adj[u][v]&&!used[1][v]) {
                used[1][v] = true;
                if(mx[v]!=-1) tracking(mx[v]);
            }
        }
    }
    bool matching(int u) {
        for(int v=0;v<n;v++){
            if (adj[u][v]&&!used[0][v]) {
                used[0][v] = true;
                if (mx[v] == -1 || matching(mx[v])) {
                    mx[v] = u;
                    return true;
                }
            }
        }
        return false;
    }
    std::vector<int> maximum_independent_set_find(){
        std::vector<int> ans;
        for(int i=0;i<n;i++){
            mx[i]=-1;
        }
        for(int i=0;i<n;i++){ // or i=0 ?
            for(int j=0;j<n;j++){
                used[0][j] = false;
            }
            matched[i] = matching(i);
        }
        for(int i=0;i<n;i++){
            used[0][i] = used[1][i] = false;
        }
        for(int i=0;i<n;i++){
            if (!matched[i]) tracking(i);
        }
        for(int i=0;i<n;i++){
            if (!(matched[i] && !used[0][i] || mx[i] != -1 && used[1][i]))
                ans.push_back(i);
        }
        return ans;
    }
} perfect_graph;
char s_p[10000000 + 750];
char *s[750], *s_pnow;
int r[750][750];
int main(){
    int i,j,k;
    int n=750;
    scanf("%d",&n);
    //
    s_pnow = s_p;
    for(i=0;i<n;i++){
        s[i]=s_pnow;
        //for(j=0;j<10000000/750-i;j++) s[i][j]='a';
        //s[i][j]=0;
        //printf("%s\n",s[i]);
        scanf("%s",s[i]);
        while(*s_pnow++);
        ac.insert(s[i],i);
    }
    ac.build_fail();
    //printf("%d\n",ac.V.size());
    for(i=0;i<n;i++){
        ac.solve(s[i],r[i]);
        //printf("%d\n",i);
        r[i][i]=0;
    }
    perfect_graph.n=n;
    perfect_graph.adj=r;
    std::vector<int> ans=perfect_graph.maximum_independent_set_find();
    printf("%d\n",ans.size());
    for(i=0;i<ans.size();i++){
        printf("%d%c",ans[i]+1," \n"[i==n-1]);
    }
}
// ntuj - kuwd8uiq8x665r2k1ha6h


#include <bits/stdc++.h>
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#ifdef _DEBUG_
	#define debug(...) printf(__VA_ARGS__)
#else
	#define debug(...) (void)0
#endif
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;

const int MAXLEN=10000010;
const int MAXN=800;

/********************************/
// dinic
const int MAXV=1600;
const int MAXE=750*749/2+1600;
const int INF=(int)1e9+10;

struct E{
	int to,co;//capacity
	E(int t=0,int c=0):to(t),co(c){}
}eg[2*MAXE];

// source:0  sink:n-1
struct Flow{
	VI e[MAXV];
	int ei,v;
	void init(int n) {
		v=n;
		ei=0;
		for(int i=0;i<n;i++)
			e[i]=VI();
	}
	void add(int a,int b,int c) { //a to b ,maxflow=c
		debug("add: %d %d %d\n",a,b,c);
		eg[ei]=E(b,c);
		e[a].PB(ei);
		ei++;
		eg[ei]=E(a,0);
		e[b].PB(ei);
		ei++;
	}

	int d[MAXV],qu[MAXV],ql,qr;
	bool BFS() {
		memset(d,-1,v*sizeof(int));
		ql=qr=0;
		qu[qr++]=0;
		d[0]=0;
		while(ql<qr && d[v-1]==-1) {
			int n=qu[ql++];
			VI &v=e[n];
			for(int i=v.size()-1;i>=0;i--) {
				int u=v[i];
				if(d[eg[u].to]==-1 && eg[u].co>0) {
					d[eg[u].to]=d[n]+1;
					qu[qr++]=eg[u].to;
				}
			}
		}
		return d[v-1]!=-1;
	}
	int ptr[MAXV];
	int go(int n,int p) {
		if(n==v-1)
			return p;
		VI &u=e[n];
		int temp;
		for(int i=ptr[n];i<SZ(u);i++)
		{
			if(d[n]+1!=d[eg[u[i]].to] || eg[u[i]].co==0)
				continue;
			if((temp=go(eg[u[i]].to,min(p,eg[u[i]].co)))==0)
				continue;
			eg[u[i]].co-=temp;
			eg[u[i]^1].co+=temp;
			ptr[n]=i;
			return temp;
		}
		ptr[n]=SZ(u);
		return 0;
	}
	int max_flow() {
		int ans=0,temp;
		while(BFS()) {
			for(int i=0;i<v;i++)
				ptr[i]=0;
			while((temp=go(0,INF))>0)
				ans+=temp;
		}
		return ans;
	}
}flow;
/****************************/

struct Trie{
	int c;
	Trie *fail,*ch[2];
	Trie():c(0){memset(ch,0,sizeof(ch));}
}trie[MAXLEN];

char in[MAXLEN+1000];
char *str[MAXN];
Trie *na,*root;
VI sameone;

inline int c_i(char a)
{
	return (int)a-'a';
}

void insert(char *s,int num)
{
	Trie *at=root;
	while(*s)
	{
		if(!at->ch[c_i(*s)])
			at->ch[c_i(*s)]=new (na++) Trie();
		at=at->ch[c_i(*s)],s++;
	}
	if(at->c)
		sameone.PB(at->c), str[at->c][0]=0;
	at->c=num;
}

Trie *q[MAXLEN];
int ql,qr;

void init()
{
	ql=qr=-1;
	q[++qr]=root;
	root->fail=NULL;
	while(ql<qr)
	{
		Trie *n=q[++ql],*f;
		for(int i=0;i<2;i++)
		{
			if(!n->ch[i])
				continue;
			f=n->fail;
			while(f && !f->ch[i])
				f=f->fail;
			n->ch[i]->fail=f?f->ch[i]:root;
			if(n->ch[i]->c==0 && n->ch[i]->fail->c!=0)
				n->ch[i]->c=n->ch[i]->fail->c;
			q[++qr]=n->ch[i];
		}
	}
}

VI e[MAXN];

int n;
void go(char *s,int num)
{
	debug("%p (%d)\n",s,*s);
	debug("%d %s\n",num,s);
	Trie*p=root;
	while(*s)
	{
		/*while(p && !p->ch[c_i(*s)])
			p=p->fail;
		p=p?p->ch[c_i(*s)]:root;*/
		p=p->ch[c_i(*s)];
		s++;
		if(p->c && *s)
			flow.add(num,n+p->c,1), e[num].PB(p->c);
		debug("%d\n",p->c);
	}
	if(p->fail && p->fail->c)
		flow.add(num,n+p->fail->c,1), e[num].PB(p->fail->c);
}

VI st;
bool vis[MAXN];
bool beto[MAXN];
int to[MAXN];
void DFS(int x) {
	vis[x]=1;
	for(int u:e[x])
		if(!vis[u])
			DFS(u);
	st.PB(x);
}

bool DFS2(int x,int p) {
	debug("DFS2(%d,%d)\n",x,p);
	vis[x]=1;
	if(!beto[x] && x!=p)
		return 0;
	for(int u:e[x])
		if(!vis[u] && !DFS2(u,p))
			return 0;
	return 1;
}

int main()
{
	na=trie;
	root=new (na++) Trie();
	scanf("%d",&n);
	str[1]=in;
	for(int i=1;i<=n;i++) {
		scanf("%s",str[i]);
		insert(str[i],i);
		str[i+1]=str[i]+strlen(str[i])+1;
	}
	init();
	const int sink=n+n+1;
	flow.init(n+n+2);
	for(int i=1;i<=n;i++)
		flow.add(0,i,1), flow.add(n+i,sink,1);
	for(int i=1;i<=n;i++)
		go(str[i],i);
	for(int i=1;i<=n;i++) {
		debug("%d:",i);
		for(int u:e[i])
			debug(" %d",u);
		debug("\n");
	}
	for(int i=1;i<=n;i++)
		if(!vis[i])
			DFS(i);
	assert(SZ(st)==n);
	reverse(ALL(st));
	VI ans;
	int number=n-flow.max_flow()-SZ(sameone);
	for(int i=1;i<=n;i++)
		for(int j:flow.e[i]) {
			debug("%d -> %d : %d\n",i,eg[j].to,eg[j].co);
			if(eg[j].co==0 && eg[j].to!=0)
				to[i]=eg[j].to-n, beto[eg[j].to-n]=1;
		}
	for(int u:sameone)
		beto[u]=1;
	/*for(int i=1;i<=n;i++)
		if(beto[i]==0)
			ans.PB(i);
	debug("%d,%d\n",SZ(ans),number);
	assert(SZ(ans)==number);*/
	assert(n<100);
	for(int x:st) {
		if(!beto[x]) {
			fill(vis,vis+n+1,0);
			if(!DFS2(x,x)) {
				beto[x]=1;
				assert(to[x]!=0);
				beto[to[x]]=0;
			}
		}
	}
	printf("%d\n",number);
	for(int i=1;i<=n;i++)
		if(!beto[i])
			printf("%d ",i);
	puts("");
	return 0;
}

// ntuj - elh9ie56ko4bcxalan10


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	node **tmp = &rt;
	for (int i = 0; ; ++i)
	{
		node *&a = *tmp;
		if (!a) a = nd + (cur++), a->p = i ? get(s[i - 1]) : 0;
		if (s[i]) tmp = &a->go[get(s[i])];
		else break;
	}
	return *tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int pos[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		pos[m] = i;
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5] = {0};
	int alln = SZ(all);
	memset(ret, 0, sizeof ret);
	{
		static int q[maxn + 5];
		static bool vis[maxn + 5] = {0};
		memset(vis, 0, sizeof vis);
		int head = 0, rear = 0;
		REP(a, 0, alln) REP(b, 0, alln)
			if (!vis[b] && a != b && f[all[a][ret[a]]][all[b][ret[b]]]) q[rear++] = b, vis[b] = 1;
		while (head != rear)
		{
			int x = q[head++];
			if (head >= maxn + 1) head -= maxn + 1;
			vis[x] = 0;
			REP(y, 0, alln)
			{
				while (f[all[y][ret[y]]][all[x][ret[x]]]) ++ret[x];
			}
			REP(y, 0, alln) if (!vis[y] && f[all[x][ret[x]]][all[y][ret[y]]])
			{
				q[rear++] = y, vis[y] = 1;
				if (rear >= maxn + 1) rear -= maxn + 1;
			}
		}
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

struct node
{
	bool p;
	node *go[2];
	node *f;

	node(): f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;
vector<node*> child[max0 + 5];

node *p[maxn + 5];

node *rt;

int dfn[max0 + 5], End[max0 + 5];
int tot = 0;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

void dfs(node *rt)
{
	int x = rt - nd;
	dfn[x] = tot++;
	for (auto y : child[rt - nd]) dfs(y);
	End[x] = tot;
}

int c[max0 + 5];

inline void add(const int &x, const int &y)
{
	for (int i = x + 1; i <= max0; i += i & -i) c[i] += y;
}

inline int query(const int &x)
{
	int ans = 0;
	for (int i = x; i > 0; i -= i & -i) ans += c[i];
	return ans;
}

int n;

bool f[maxn + 5][maxn + 5];

int pos[maxn + 5], len[maxn + 5];

inline bool cmp(int x, int y)
{
	return len[x] < len[y];
}

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	int w;
	static char s[max0 + 5];
	scanf("%d", &w);
	n = w;
	REP(i, 0, w)
	{
		pos[i] = i;
		scanf("%s", s);
		len[i] = strlen(s);
		p[i] = add(rt, s);
	}
	sort(pos, pos + n, cmp);
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	while (head != rear)
	{
		node *x = q[head++];
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 1, rear) child[q[i]->f - nd].pb(q[i]);
	dfs(rt);
	REP(i, 0, cur) nd[i].f = NULL;
	for (int i = rear - 1; i >= 0; --i)
	{
		REP(j, 0, 2)
			if (q[i]->go[j]) q[i]->go[j]->f = q[i];
	}
	nd[0].f = NULL;
	REP(i, 1, n)
	{
		node *now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], 1);
			now = now->f;
		}
		REP(j, 0, i)
		{
			int tmp = p[pos[j]] - nd;
			f[i][j] = query(End[tmp]) - query(dfn[tmp]);
		}
		now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], -1);
			now = now->f;
		}
	}
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	static bool vis[maxn + 5];
	REP(i, 0, n)
	{
		if (vis[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			vis[u] = 1;
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
			if (flag) break;
			++ret[i];
		}
		REP(j, 0, i)
			while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int pos[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		pos[m] = i;
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5] = {0};
	int alln = SZ(all);
	memset(ret, 0, sizeof ret);
	{
		static int q[maxn + 5];
		static bool vis[maxn + 5] = {0};
		memset(vis, 0, sizeof vis);
		int head = 0, rear = 0;
		REP(a, 0, alln)
			REP(b, 0, alln)
			if (a != b && f[all[a][ret[a]]][all[b][ret[b]]]) q[rear++] = b, vis[b] = 1;
		while (head != rear)
		{
			int x = q[rear++];
			vis[x] = 0;
			REP(y, 0, n) while (f[all[y][ret[y]]][all[x][ret[x]]]) ++ret[x];
			REP(y, 0, n) if (!vis[y] && f[all[x][ret[x]]][all[y][ret[y]]]) q[rear++] = y, vis[y] = 1;
		}
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

struct node
{
    bool p;
    node *go[2];
    node *f;

    node(): f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;
vector<node*> child[max0 + 5];

node *p[maxn + 5];

node *rt;

int dfn[max0 + 5], End[max0 + 5];
int tot = 0;

node *add(node *&rt, char *s)
{
    if (rt == NULL) rt = nd + (cur++);
    if (!s[0]) return rt;
    node *tmp = add(rt->go[get(s[0])], s + 1);
    rt->go[get(s[0])]->p = get(s[0]);
    return tmp;
}

void dfs(node *rt)
{
    int x = rt - nd;
    dfn[x] = tot++;
    for (auto y : child[rt - nd]) dfs(y);
    End[x] = tot;
}

int c[max0 + 5];

inline void add(const int &x, const int &y)
{
    for (int i = x + 1; i <= max0; i += i & -i) c[i] += y;
}

inline int query(const int &x)
{
    int ans = 0;
    for (int i = x; i > 0; i -= i & -i) ans += c[i];
    return ans;
}

int n;

bool f[maxn + 5][maxn + 5];

int pos[maxn + 5], len[maxn + 5];

inline bool cmp(int x, int y)
{
    return len[x] < len[y];
}

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
    REP(y, 0, n)
        if (f[x][y] && !vis[y])
        {
            vis[y] = 1;
            if (link[y] == -1 || find(link[y]))
            {
                link[y] = x;
                return 1;
            }
        }
    return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    rt = nd + (cur++);
    int w;
    static char s[max0 + 5];
    scanf("%d", &w);
    n = w;
    REP(i, 0, w)
    {
        pos[i] = i;
        scanf("%s", s);
        len[i] = strlen(s);
        p[i] = add(rt, s);
    }
    sort(pos, pos + n, cmp);
    static node *q[max0 + 5];
    int head = 0, rear = 0;
    q[rear++] = rt;
    rt->f = rt;
    while (head != rear)
    {
        node *x = q[head++];
        for (int i = 0; i < 2; ++i)
        {
            node *y = x->go[i];
            if (!y)
            {
                x->go[i] = x == rt ? rt : x->f->go[i];
            }
            else
            {
                q[rear++] = y;
                y->f = x == rt ? x : x->f->go[y->p];
            }
        }
    }
    REP(i, 1, rear) child[q[i]->f - nd].pb(q[i]);
    dfs(rt);
    REP(i, 1, rear) child[q[i]->f - nd].clear();
    REP(i, 0, cur) nd[i].f = NULL;
    for (int i = rear - 1; i >= 0; --i)
    {
        REP(j, 0, 2)
            if (q[i]->go[j]) q[i]->go[j]->f = q[i];
    }
    nd[0].f = NULL;
    REP(i, 1, n)
    {
        node *now = p[pos[i]];
        while (now)
        {
            add(dfn[now - nd], 1);
            now = now->f;
        }
        REP(j, 0, i)
        {
            int tmp = p[pos[j]] - nd;
            f[i][j] = query(End[tmp]) - query(dfn[tmp]);
        }
        now = p[pos[i]];
        while (now)
        {
            add(dfn[now - nd], -1);
            now = now->f;
        }
    }
    memset(link, -1, sizeof link);
    int ans = 0;
    REP(i, 0, n)
    {
        memset(vis, 0, sizeof vis);
        if (!find(i)) ++ans;
    }
    vector<vector<int> > all;
    static bool vis[maxn + 5];
    REP(i, 0, n)
    {
        if (vis[i]) continue;
        int u = i;
        vector<int> tmp;
        while (u != -1)
        {
            vis[u] = 1;
            tmp.pb(u);
            u = link[u];
        }
        all.pb(tmp);
    }
    printf("%d\n", ans);
    static int ret[maxn + 5];
    int alln = SZ(all);
    REP(i, 0, alln)
    {
        ret[i] = 0;
        while (1)
        {
            bool flag = 1;
            REP(j, 0, i)
                if (f[all[j][ret[j]]][all[i][ret[i]]])
                {
                    flag = 0;
                    break;
                }
            if (flag) break;
            ++ret[i];
        }
        REP(j, 0, i)
            while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
    }
    REP(i, 0, alln)
    {
        printf("%d ", pos[all[i][ret[i]]] + 1);
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int pos[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		pos[m] = i;
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
			if (flag) break;
			++ret[i];
		}
		REP(j, 0, i)
			while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
			if (flag) break;
			++ret[i];
		}
		REP(j, 0, i)
			while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
	}
	REP(i, 0, alln)
	{
		printf("%d ", all[i][ret[i]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

struct node
{
	bool p;
	node *go[2];
	node *f;

	node(): f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;
vector<int> child[max0 + 5];

node *p[maxn + 5];

node *rt;

int dfn[max0 + 5], End[max0 + 5];
int tot = 0;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

void dfs(node *rt)
{
	int x = rt - nd;
	dfn[x] = tot++;
	for (auto y : child[rt - nd]) dfs(nd + y);
	End[x] = tot;
}

int c[max0 + 5];

inline void add(const int &x, const int &y)
{
	for (int i = x + 1; i <= max0; i += i & -i) c[i] += y;
}

inline int query(const int &x)
{
	int ans = 0;
	for (int i = x; i > 0; i -= i & -i) ans += c[i];
	return ans;
}

int n;

bool f[maxn + 5][maxn + 5];

int pos[maxn + 5], len[maxn + 5];

inline bool cmp(int x, int y)
{
	return len[x] < len[y];
}

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	int w;
	static char s[max0 + 5];
	scanf("%d", &w);
	n = w;
	REP(i, 0, w)
	{
		pos[i] = i;
		scanf("%s", s);
		len[i] = strlen(s);
		p[i] = add(rt, s);
	}
	sort(pos, pos + n, cmp);
	static int q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt - nd;
	rt->f = rt;
	while (head != rear)
	{
		node *x = nd + q[head++];
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y - nd;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 1, rear) child[(nd + q[i])->f - nd].pb(q[i]);
	dfs(rt);
	REP(i, 1, rear) child[(nd + q[i])->f - nd].clear();
	REP(i, 0, cur) nd[i].f = NULL;
	for (int i = rear - 1; i >= 0; --i)
	{
		REP(j, 0, 2)
			if ((nd + q[i])->go[j]) (nd + q[i])->go[j]->f = nd + q[i];
	}
	nd[0].f = NULL;
	REP(i, 1, n)
	{
		node *now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], 1);
			now = now->f;
		}
		REP(j, 0, i)
		{
			int tmp = p[pos[j]] - nd;
			f[i][j] = query(End[tmp]) - query(dfn[tmp]);
		}
		now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], -1);
			now = now->f;
		}
	}
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	static bool vis[maxn + 5];
	REP(i, 0, n)
	{
		if (vis[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			vis[u] = 1;
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
			if (flag) break;
			++ret[i];
		}
		REP(j, 0, i)
			while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int pos[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		pos[m] = i;
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5] = {0};
	int alln = SZ(all);
	memset(ret, 0, sizeof ret);
	{
		static int q[maxn + 5];
		static bool vis[maxn + 5] = {0};
		memset(vis, 0, sizeof vis);
		int head = 0, rear = 0;
		REP(a, 0, alln) REP(b, 0, alln)
			if (!vis[b] && a != b && f[all[a][ret[a]]][all[b][ret[b]]]) q[rear++] = b, vis[b] = 1;
		while (head != rear)
		{
			int x = q[head++];
			if (head >= maxn + 1) head -= maxn + 1;
			vis[x] = 0;
			REP(y, 0, alln)
			{
				while (f[all[y][ret[y]]][all[x][ret[x]]]) ++ret[x];
			}
			REP(y, 0, alln) if (!vis[y] && f[all[x][ret[x]]][all[y][ret[y]]])
			{
				q[rear++] = y, vis[y] = 1;
				if (rear >= maxn + 1) rear -= maxn + 1;
			}
		}
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int pos[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		pos[m] = i;
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
				else while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
			if (flag) break;
			++ret[i];
		}
	}
	REP(i, 0, alln)
		REP(j, 0, alln)
			if (i != j) assert(!f[all[i][ret[i]]][all[j][ret[j]]]);
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

struct node
{
	bool p;
	node *go[2];
	node *f;

	node(): f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;
vector<node*> child[max0 + 5];

node *p[maxn + 5];

node *rt;

int dfn[max0 + 5], End[max0 + 5];
int tot = 0;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

void dfs(node *rt)
{
	int x = rt - nd;
	dfn[x] = tot++;
	for (auto y : child[rt - nd]) dfs(y);
	End[x] = tot;
}

int c[max0 + 5];

inline void add(const int &x, const int &y)
{
	for (int i = x + 1; i <= max0; i += i & -i) c[i] += y;
}

inline int query(const int &x)
{
	int ans = 0;
	for (int i = x; i > 0; i -= i & -i) ans += c[i];
	return ans;
}

int n;

bool f[maxn + 5][maxn + 5];

int pos[maxn + 5], len[maxn + 5];

inline bool cmp(int x, int y)
{
	return len[x] < len[y];
}

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	int w;
	static char s[max0 + 5];
	scanf("%d", &w);
	n = w;
	REP(i, 0, w)
	{
		pos[i] = i;
		scanf("%s", s);
		len[i] = strlen(s);
		p[i] = add(rt, s);
	}
	sort(pos, pos + n, cmp);
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	while (head != rear)
	{
		node *x = q[head++];
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 1, rear) child[q[i]->f - nd].pb(q[i]);
	dfs(rt);
	REP(i, 1, rear) child[q[i]->r - nd].clear();
	REP(i, 0, cur) nd[i].f = NULL;
	for (int i = rear - 1; i >= 0; --i)
	{
		REP(j, 0, 2)
			if (q[i]->go[j]) q[i]->go[j]->f = q[i];
	}
	nd[0].f = NULL;
	REP(i, 1, n)
	{
		node *now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], 1);
			now = now->f;
		}
		REP(j, 0, i)
		{
			int tmp = p[pos[j]] - nd;
			f[i][j] = query(End[tmp]) - query(dfn[tmp]);
		}
		now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], -1);
			now = now->f;
		}
	}
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	static bool vis[maxn + 5];
	REP(i, 0, n)
	{
		if (vis[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			vis[u] = 1;
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
			if (flag) break;
			++ret[i];
		}
		REP(j, 0, i)
			while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

struct node
{
	int p;
	node *pa;
	node *go[2];
	node *f;

	node(): f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;
vector<node*> child[max0 + 5];

node *p[max0 + 5];

node *rt;

int dfn[max0 + 5], End[max0 + 5];
int tot = 0;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	rt->go[get(s[0])]->pa = rt;
	return tmp;
}

void dfs(node *rt)
{
	int x = rt - nd;
	dfn[x] = tot++;
	for (auto y : child[rt - nd]) dfs(y);
	End[x] = tot;
}

int c[max0 + 5];

inline void add(const int &x, const int &y)
{
	for (int i = x + 1; i <= max0; i += i & -i) c[i] += y;
}

inline int query(const int &x)
{
	int ans = 0;
	for (int i = x; i > 0; i -= i & -i) ans += c[i];
	return ans;
}

int n;

bool f[maxn + 5][maxn + 5];

int pos[maxn + 5], len[maxn + 5];

inline bool cmp(int x, int y)
{
	return len[x] < len[y];
}

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	int w;
	static char s[max0 + 5];
	scanf("%d", &w);
	n = w;
	REP(i, 0, w)
	{
		pos[i] = i;
		scanf("%s", s);
		len[i] = strlen(s);
		p[i] = add(rt, s);
	}
	sort(pos, pos + n, cmp);
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	while (head != rear)
	{
		node *x = q[head++];
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 1, rear) child[q[i]->f - nd].pb(q[i]);
	dfs(rt);
	REP(i, 1, n)
	{
		node *now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], 1);
			now = now->pa;
		}
		REP(j, 0, i)
		{
			int tmp = p[pos[j]] - nd;
			f[i][j] = query(End[tmp]) - query(dfn[tmp]);
		}
		now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], -1);
			now = now->pa;
		}
	}
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	static bool vis[maxn + 5];
	REP(i, 0, n)
	{
		if (vis[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			vis[u] = 1;
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	int lst = -1;
	REP(i, 0, SZ(all))
	{
		REP(j, 0, SZ(all[i]))
		{
			if (lst == -1 || !f[all[i][j]][lst])
			{
				lst = all[i][j];
				break;
			}
		}
		printf("%d ", pos[lst] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 10000000;

int get(char c) { return c == 'b'; }

int id;

struct node
{
	int id;
	bool p;
	node *go[2];
	node *f;
	node *lst;

	node(): id(-1), f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;

node *p[maxn + 5];

node *rt;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	return tmp;
}

int n;

bool f[maxn + 5][maxn + 5];

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int l[maxn + 5], r[maxn + 5];

int deg[maxn + 5];

int pos[maxn + 5];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	static char s[max0 + 5];
	scanf("%d", &n);
	int tot_len = 0;
	int m = 0;
	REP(i, 0, n)
	{
		scanf("%s", s + tot_len);
		pos[m] = i;
		l[m] = tot_len;
		p[m] = add(rt, s + tot_len);
		tot_len = r[m] = tot_len + strlen(s + tot_len);
		if (p[m]->id == -1)
		{
			p[m]->id = m;
			++m;
		}
	}
	n = m;
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	rt->lst = rt;
	while (head != rear)
	{
		node *x = q[head++];
		if (x->id != -1) x->lst = x;
		else x->lst = x->f->lst;
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 0, n)
	{
		node *now = rt;
		REP(j, l[i], r[i])
		{
			now = now->go[get(s[j])];
			if (j == r[i] - 1) now = now->f;
			assert(now);
			assert(now->lst);
			if (now->lst->id >= 0) f[i][now->lst->id] = 1;
		}
	}
	REP(k, 0, n)
		REP(i, 0, n)
			REP(j, 0, n)
				if (f[i][k] && f[k][j]) f[i][j] = 1;
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	memset(deg, 0, sizeof deg);
	REP(i, 0, n) if (link[i] != -1) ++deg[link[i]];
	REP(i, 0, n)
	{
		if (deg[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	static int ret[maxn + 5];
	int alln = SZ(all);
	REP(i, 0, alln)
	{
		ret[i] = 0;
		while (1)
		{
			bool flag = 1;
			REP(j, 0, i)
				if (f[all[j][ret[j]]][all[i][ret[i]]])
				{
					flag = 0;
					break;
				}
				else while (f[all[i][ret[i]]][all[j][ret[j]]]) ++ret[j];
			if (flag) break;
			++ret[i];
		}
	}
	REP(i, 0, alln)
	{
		printf("%d ", pos[all[i][ret[i]]] + 1);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 750;
const int max0 = 1000000;

int get(char c) { return c == 'b'; }

struct node
{
	int p;
	node *pa;
	node *go[2];
	node *f;

	node(): f(NULL) { memset(go, 0, sizeof go); }
};

node nd[max0 + 5];
int cur = 0;
vector<node*> child[max0 + 5];

node *p[max0 + 5];

node *rt;

int dfn[max0 + 5], End[max0 + 5];
int tot = 0;

node *add(node *&rt, char *s)
{
	if (rt == NULL) rt = nd + (cur++);
	if (!s[0]) return rt;
	node *tmp = add(rt->go[get(s[0])], s + 1);
	rt->go[get(s[0])]->p = get(s[0]);
	rt->go[get(s[0])]->pa = rt;
	return tmp;
}

void dfs(node *rt)
{
	int x = rt - nd;
	dfn[x] = tot++;
	for (auto y : child[rt - nd]) dfs(y);
	End[x] = tot;
}

int c[max0 + 5];

inline void add(const int &x, const int &y)
{
	for (int i = x + 1; i <= max0; i += i & -i) c[i] += y;
}

inline int query(const int &x)
{
	int ans = 0;
	for (int i = x; i > 0; i -= i & -i) ans += c[i];
	return ans;
}

int n;

bool f[maxn + 5][maxn + 5];

int pos[maxn + 5], len[maxn + 5];

inline bool cmp(int x, int y)
{
	return len[x] < len[y];
}

int link[maxn + 5];
bool vis[maxn + 5];

inline bool find(int x)
{
	REP(y, 0, n)
		if (f[x][y] && !vis[y])
		{
			vis[y] = 1;
			if (link[y] == -1 || find(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
	return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	rt = nd + (cur++);
	int w;
	static char s[max0 + 5];
	scanf("%d", &w);
	n = w;
	REP(i, 0, w)
	{
		pos[i] = i;
		scanf("%s", s);
		len[i] = strlen(s);
		p[i] = add(rt, s);
	}
	sort(pos, pos + n, cmp);
	static node *q[max0 + 5];
	int head = 0, rear = 0;
	q[rear++] = rt;
	rt->f = rt;
	while (head != rear)
	{
		node *x = q[head++];
		for (int i = 0; i < 2; ++i)
		{
			node *y = x->go[i];
			if (!y)
			{
				x->go[i] = x == rt ? rt : x->f->go[i];
			}
			else
			{
				q[rear++] = y;
				y->f = x == rt ? x : x->f->go[y->p];
			}
		}
	}
	REP(i, 1, rear) child[q[i]->f - nd].pb(q[i]);
	dfs(rt);
	REP(i, 1, n)
	{
		node *now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], 1);
			now = now->pa;
		}
		REP(j, 0, i)
		{
			int tmp = p[pos[j]] - nd;
			f[i][j] = query(End[tmp]) - query(dfn[tmp]);
		}
		now = p[pos[i]];
		while (now)
		{
			add(dfn[now - nd], -1);
			now = now->pa;
		}
	}
	memset(link, -1, sizeof link);
	int ans = 0;
	REP(i, 0, n)
	{
		memset(vis, 0, sizeof vis);
		if (!find(i)) ++ans;
	}
	vector<vector<int> > all;
	static bool vis[maxn + 5];
	REP(i, 0, n)
	{
		if (vis[i]) continue;
		int u = i;
		vector<int> tmp;
		while (u != -1)
		{
			vis[u] = 1;
			tmp.pb(u);
			u = link[u];
		}
		all.pb(tmp);
	}
	printf("%d\n", ans);
	int lst = -1;
	REP(i, 0, SZ(all))
	{
		REP(j, 0, SZ(all[i]))
		{
			if (lst == -1 || !f[all[i][j]][lst])
			{
				lst = all[i][j];
				break;
			}
		}
		printf("%d ", pos[lst] + 1);
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define M 1000000007
#define all(a) a.begin(), a.end()

const int maxn = 760, maxm = 10001000;
int n;
char s[maxm];
int go[maxm][2], fail[maxm], root = 1, tot = 1;
int last[maxm], cnt[maxm];
int b[maxn][maxn];
bool vis[maxn];
int p[maxn], bg[maxn];

void insert(char *str, int id){
	int cur = root, i = 0;
	while(str[i]){
		int idx = str[i] - 'a';
		if(!go[cur][idx]) go[cur][idx] = ++tot;
		cur = go[cur][idx];
		i++;
	}
	cnt[cur] = id;
}

void build(){
	queue<int> q;
	q.push(root);
	while(!q.empty()){
		int t = q.front(); q.pop();
		for(int i = 0; i < 2; ++i)
			if(!go[t][i]){
				go[t][i] = t == root ? 1 : go[fail[t]][i];
			}else{
				fail[go[t][i]] = t == root ? 1 : go[fail[t]][i];
				last[go[t][i]] = cnt[fail[go[t][i]]] ? fail[go[t][i]] :
					last[fail[go[t][i]]];
				q.push(go[t][i]);
			}
	}
}

bool dfs(int t){
	for(int i = 1; i <= n; ++i)
		if(b[t][i] && !vis[i]){
			vis[i] = 1;
			if(!p[i] || dfs(p[i])){
				p[i] = t;
				return 1;
			}
		}
	return 0;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", s + bg[i]);
		bg[i + 1] = bg[i] + strlen(s + bg[i]);
		insert(s + bg[i], i);
	}
	build();
	for(int i = 1; i <= n; ++i){
		int cur = root;
		for(int j = bg[i]; j < bg[i + 1]; ++j){
			cur = go[cur][s[j] - 'a'];
			b[i][cnt[last[cur]]] = 1;
			b[i][cnt[cur]] = 1;
		}
	}
	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				b[i][j] |= b[i][k] && b[k][j];
	for(int i = 1; i <= n; ++i) b[i][i] = 0;

	int res = n;
	for(int i = 1; i <= n; ++i){
		memset(vis, 0, sizeof(vis));
		res -= dfs(i);
	}
	printf("%d\n", res);
	for(int i = 1; i <= n; ++i)
		if(!p[i]) printf("%d ", i);

#ifndef ONLINE_JUDGE
	system("pause");
#endif
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define M 1000000007
#define all(a) a.begin(), a.end()

const int maxn = 760, maxm = 10001000;
int n;
char s[maxm];
int go[maxm][2], fail[maxm], root = 1, tot = 1;
int last[maxm], cnt[maxm];
int b[maxn][maxn];
bool vis[maxn];
int p[maxn], bg[maxn], q[maxn];
bool mark[maxn][2];

void insert(char *str, int id){
	int cur = root, i = 0;
	while(str[i]){
		int idx = str[i] - 'a';
		if(!go[cur][idx]) go[cur][idx] = ++tot;
		cur = go[cur][idx];
		i++;
	}
	cnt[cur] = id;
}

void build(){
	queue<int> q;
	q.push(root);
	while(!q.empty()){
		int t = q.front(); q.pop();
		for(int i = 0; i < 2; ++i)
			if(!go[t][i]){
				go[t][i] = t == root ? 1 : go[fail[t]][i];
			}else{
				fail[go[t][i]] = t == root ? 1 : go[fail[t]][i];
				last[go[t][i]] = cnt[fail[go[t][i]]] ? fail[go[t][i]] :
					last[fail[go[t][i]]];
				q.push(go[t][i]);
			}
	}
}

bool dfs(int t){
	for(int i = 1; i <= n; ++i)
		if(b[t][i] && !vis[i]){
			vis[i] = 1;
			if(!p[i] || dfs(p[i])){
				p[i] = t;
				q[t] = i;
				return 1;
			}
		}
	return 0;
}

void dfs(int x, int side){
	if(mark[x][side]) return;
	mark[x][side] = 1;
	if(!side){
		for(int i = 1; i <= n; ++i)
			if(b[x][i]) dfs(i, 1);
	}else{
		if(p[x]) dfs(p[x], 0);
	}
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", s + bg[i]);
		bg[i + 1] = bg[i] + strlen(s + bg[i]);
		insert(s + bg[i], i);
	}
	build();
	for(int i = 1; i <= n; ++i){
		int cur = root;
		for(int j = bg[i]; j < bg[i + 1]; ++j){
			cur = go[cur][s[j] - 'a'];
			b[i][cnt[last[cur]]] = 1;
			b[i][cnt[cur]] = 1;
		}
	}
	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				b[i][j] |= b[i][k] && b[k][j];
	for(int i = 1; i <= n; ++i) b[i][i] = 0;

	int res = n;
	for(int i = 1; i <= n; ++i){
		memset(vis, 0, sizeof(vis));
		res -= dfs(i);
	}
	printf("%d\n", res);
	for(int i = 1; i <= n; ++i)
		if(!q[i]) dfs(i, 0);
	for(int i = 1; i <= n; ++i)
		if(!(q[i] && !mark[i][0] || p[i] && mark[i][1]))
			printf("%d ", i);

#ifndef ONLINE_JUDGE
	system("pause");
#endif
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define M 1000000007
#define all(a) a.begin(), a.end()

const int maxn = 760, maxm = 10001000;
int n;
char s[maxm];
int go[maxm][2], fail[maxm], root = 1, tot = 1;
int last[maxm], cnt[maxm];
int b[maxn][maxn];
bool vis[maxn];
int p[maxn], bg[maxn], q[maxn];
bool mark[maxn][2];

void insert(char *str, int id){
	int cur = root, i = 0;
	while(str[i]){
		int idx = str[i] - 'a';
		if(!go[cur][idx]) go[cur][idx] = ++tot;
		cur = go[cur][idx];
		i++;
	}
	cnt[cur] = id;
}

void build(){
	queue<int> q;
	q.push(root);
	while(!q.empty()){
		int t = q.front(); q.pop();
		for(int i = 0; i < 2; ++i)
			if(!go[t][i]){
				go[t][i] = t == root ? 1 : go[fail[t]][i];
			}else{
				fail[go[t][i]] = t == root ? 1 : go[fail[t]][i];
				last[go[t][i]] = cnt[fail[go[t][i]]] ? fail[go[t][i]] :
					last[fail[go[t][i]]];
				q.push(go[t][i]);
			}
	}
}

bool dfs(int t){
	for(int i = 1; i <= n; ++i)
		if(b[t][i] && !vis[i]){
			vis[i] = 1;
			if(!p[i] || dfs(p[i])){
				p[i] = t;
				q[t] = i;
				return 1;
			}
		}
	return 0;
}

void dfs(int x, int side){
	if(mark[x][side]) return;
	mark[x][side] = 1;
	if(!side){
		for(int i = 1; i <= n; ++i)
			if(b[x][i]) dfs(i, 1);
	}else{
		if(p[x]) dfs(p[x], 0);
	}
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", s + bg[i]);
		bg[i + 1] = bg[i] + strlen(s + bg[i]);
		insert(s + bg[i], i);
	}
	build();
	for(int i = 1; i <= n; ++i){
		int cur = root;
		for(int j = bg[i]; j < bg[i + 1]; ++j){
			cur = go[cur][s[j] - 'a'];
			b[i][cnt[last[cur]]] = 1;
			b[i][cnt[cur]] = 1;
		}
	}
	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				b[i][j] |= b[i][k] && b[k][j];
	for(int i = 1; i <= n; ++i) b[i][i] = 0;

	int res = n;
	for(int i = 1; i <= n; ++i){
		memset(vis, 0, sizeof(vis));
		res -= dfs(i);
	}
	printf("%d\n", res);
	for(int i = 1; i <= n; ++i)
		if(!q[i]) dfs(i, 0);
	for(int i = 1; i <= n; ++i)
		if(!(mark[i][1] || !mark[i][0]))
			printf("%d ", i);

#ifndef ONLINE_JUDGE
	system("pause");
#endif
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define M 1000000007
#define all(a) a.begin(), a.end()

const int maxn = 760, maxm = 10001000;
int n;
char s[maxm];
int go[maxm][2], fail[maxm], root = 1, tot = 1;
int last[maxm], cnt[maxm];
int b[maxn][maxn];
bool vis[maxn];
int p[maxn], bg[maxn], q[maxn];
bool mark[maxn][2];

void insert(char *str, int id){
	int cur = root, i = 0;
	while(str[i]){
		int idx = str[i] - 'a';
		if(!go[cur][idx]) go[cur][idx] = ++tot;
		cur = go[cur][idx];
		i++;
	}
	cnt[cur] = id;
}

void build(){
	queue<int> q;
	q.push(root);
	while(!q.empty()){
		int t = q.front(); q.pop();
		for(int i = 0; i < 2; ++i)
			if(!go[t][i]){
				go[t][i] = t == root ? 1 : go[fail[t]][i];
			}else{
				fail[go[t][i]] = t == root ? 1 : go[fail[t]][i];
				last[go[t][i]] = cnt[fail[go[t][i]]] ? fail[go[t][i]] :
					last[fail[go[t][i]]];
				q.push(go[t][i]);
			}
	}
}

bool dfs(int t){
	for(int i = 1; i <= n; ++i)
		if(b[t][i] && !vis[i]){
			vis[i] = 1;
			if(!p[i] || dfs(p[i])){
				p[i] = t;
				q[t] = i;
				return 1;
			}
		}
	return 0;
}

void dfs(int x, int side){
	if(mark[x][side]) return;
	mark[x][side] = 1;
	if(!side){
		for(int i = 0; i < n; ++i)
			if(b[x][i]) dfs(i, 1);
	}else{
		if(p[x]) dfs(p[x], 0);
	}
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", s + bg[i]);
		bg[i + 1] = bg[i] + strlen(s + bg[i]);
		insert(s + bg[i], i);
	}
	build();
	for(int i = 1; i <= n; ++i){
		int cur = root;
		for(int j = bg[i]; j < bg[i + 1]; ++j){
			cur = go[cur][s[j] - 'a'];
			b[i][cnt[last[cur]]] = 1;
			b[i][cnt[cur]] = 1;
		}
	}
	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				b[i][j] |= b[i][k] && b[k][j];
	for(int i = 1; i <= n; ++i) b[i][i] = 0;

	int res = n;
	for(int i = 1; i <= n; ++i){
		memset(vis, 0, sizeof(vis));
		res -= dfs(i);
	}
	printf("%d\n", res);
	for(int i = 1; i <= n; ++i)
		if(!q[i]) dfs(i, 0);
	for(int i = 1; i <= n; ++i)
		if(!(q[i] && !mark[i][0] || p[i] && mark[i][1]))
			printf("%d ", i);

#ifndef ONLINE_JUDGE
	system("pause");
#endif
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define M 1000000007
#define all(a) a.begin(), a.end()

const int maxn = 760, maxm = 10001000;
int n;
char s[maxm];
int go[maxm][2], fail[maxm], root = 1, tot = 1;
int last[maxm], cnt[maxm];
int b[maxn][maxn];
bool vis[maxn];
int p[maxn], bg[maxn];

void insert(char *str, int id){
	int cur = root, i = 0;
	while(str[i]){
		int idx = str[i] - 'a';
		if(!go[cur][idx]) go[cur][idx] = ++tot;
		cur = go[cur][idx];
		i++;
	}
	cnt[cur] = id;
}

void build(){
	queue<int> q;
	q.push(root);
	while(!q.empty()){
		int t = q.front(); q.pop();
		for(int i = 0; i < 2; ++i)
			if(!go[t][i]){
				go[t][i] = t == root ? 1 : go[fail[t]][i];
			}else{
				fail[go[t][i]] = t == root ? 1 : go[fail[t]][i];
				last[go[t][i]] = cnt[fail[go[t][i]]] ? cnt[fail[go[t][i]]] :
					last[fail[go[t][i]]];
				q.push(go[t][i]);
			}
	}
}

void dfs(int c, int t){
	for(int i = 1; i <= n; ++i)
		if(!b[c][i] && b[t][i]){
			b[c][i] = 1;
			dfs(c, i);
		}
}

bool dfs(int t){
	for(int i = 1; i <= n; ++i)
		if(b[t][i] && !vis[i]){
			vis[i] = 1;
			if(!p[i] || dfs(p[i])){
				p[i] = t;
				return 1;
			}
		}
	return 0;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", s + bg[i]);
		bg[i + 1] = bg[i] + strlen(s + bg[i]);
		insert(s + bg[i], i);
	}
	build();
	for(int i = 1; i <= n; ++i){
		int cur = root;
		for(int j = bg[i]; j < bg[i + 1]; ++j){
			cur = go[cur][s[j] - 'a'];
			b[i][last[cur]] = 1;
			b[i][cnt[cur]] = 1;
		}
	}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			if(b[i][j]) dfs(i, j);
	for(int i = 1; i <= n; ++i) b[i][i] = 0;
	int res = n;
	for(int i = 1; i <= n; ++i){
		memset(vis, 0, sizeof(vis));
		res -= dfs(i);
	}
	printf("%d\n", res);
	for(int i = 1; i <= n; ++i)
		if(!p[i]) printf("%d ", i);

#ifndef ONLINE_JUDGE
	system("pause");
#endif
	return 0;
}


#include<bits/stdc++.h>
#define N 10000005
#define INF 2147483646 / 2
using namespace std;
struct edge {
	int v, nxt, c;
} e[ 1505 * 2];
int p[1505], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void insert(int u, int v, int c) {
	e[eid].v = v;
	e[eid].c = c;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
void add(int u, int v, int c) {
	insert(u, v, c);
	insert(v, u, 0);
}
int ch[N][2], cnt[N], tot, ys[1505], nxt[N], g[755][755], L[1505], R[1505], ha[N];
string st;
queue<int> q;
void insert(int id) {
	int p = 0, len = st.length();
	L[id] = ha[0] + 1;
	for(int i = 0; i < len; i ++) {
		ha[++ ha[0]] = st[i] - 'a';
		if(!ch[p][st[i] - 'a']) ch[p][st[i] - 'a'] = ++ tot;
		p = ch[p][st[i] - 'a'];
	}
//	printf("%d ", p);
	cnt[p] = id;
	R[id] = ha[0];
}
void build() {
	for(int i = 0; i < 2; i ++)
		if(ch[0][i]) q.push(ch[0][i]);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = 0; i < 2; i ++) {
			if(!ch[u][i]) ch[u][i] = ch[nxt[u]][i];
			else nxt[ch[u][i]] = ch[nxt[u]][i], q.push(ch[u][i]);
		}
	}
}
int vis[N];
void run(int id) { //printf("%d %d\n", L[id], R[id]);
	int p = 0;
	vis[0] = 1;
	for(int i = L[id]; i <= R[id]; i ++) {
		p = ch[p][ha[i]];//printf("*%d*", p);
		int pp = p, tt;
		while(pp) { //printf("%d ", pp);
			if(cnt[pp] && cnt[pp] != id) {
				g[id][cnt[pp]] = 1;// printf("%d --> %d\n", id, cnt[pp]);
				break;
			}
			pp = nxt[pp];
		}
		int haha = pp;
		pp = p;
		while(pp) { //printf("%d ", pp);
			if(cnt[pp] && cnt[pp] != id) {
				break;
			}
			tt = pp;
			pp = nxt[pp];
			nxt[tt] = haha;

		}
	}
}

int dis[1505], S, T, n;
int bfs() {
	memset(dis, -1, sizeof dis);
	dis[S] = 1;
	q.push(S);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = p[u]; i + 1; i = e[i].nxt) {
			int v = e[i].v;
			if(dis[v] == -1 && e[i].c) {
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	return dis[T] != -1;
}
int dfs(int u, int flow) { //printf("%d %d\n", u, flow);
	if(u == T) return flow;
	int ret = 0;
	for(int i = p[u]; i + 1; i = e[i].nxt) {
		int c = e[i].c, v = e[i].v;
		if(c && dis[v] == dis[u] + 1) {
			int tmp = dfs(v, min(flow, c));
			ret += tmp, flow -= tmp;
			e[i].c -= tmp, e[i^1].c += tmp;
			if(!flow) break;
		}
	}
	if(!ret) dis[u] = -1;
	return ret;
}
int Dinic() {
	int ret = 0;
	for(;bfs();) ret += dfs(S, INF);
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	init();
	cin >> n; T = 2 * n + 1;
	for(int i = 1; i <= n; i ++) cin >> st, insert(i);
	build();
	for(int i = 1; i <= n; i ++) run(i);
	for(int k = 1; k <= n; k ++)
		for(int i = 1; i <= n; i ++)
			for(int j = 1; j <= n; j ++)
				g[i][j] |= (g[i][k] & g[k][j]);
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			if(g[i][j] && i != j) add(i, j + n, 1);
	for(int i = 1; i <= n; i ++) add(S, i, 1), add(i + n, T, 1), vis[i + n] = 0;
	cout << n - Dinic() << endl;
	for(int i = 1; i <= n; i ++) if(dis[i] != -1 && dis[i + n] == -1) cout << i << ' ';
	return 0;
}


#include<bits/stdc++.h>
#define N 10000005
#define INF 2147483646 / 2
using namespace std;
struct edge {
	int v, nxt, c;
} e[ 1505 * 1505 * 2];
int p[1505], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void insert(int u, int v, int c) {
	e[eid].v = v;
	e[eid].c = c;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
void add(int u, int v, int c) {
	insert(u, v, c);
	insert(v, u, 0);
}
int ch[N][2], cnt[N], tot, ys[1505], nxt[N], g[755][755], L[1505], R[1505], ha[N];
string st;
queue<int> q;
void insert(int id) {
	int p = 0, len = st.length();
	L[id] = ha[0] + 1;
	for(int i = 0; i < len; i ++) {
		ha[++ ha[0]] = st[i] - 'a';
		if(!ch[p][st[i] - 'a']) ch[p][st[i] - 'a'] = ++ tot;
		p = ch[p][st[i] - 'a'];
	}
//	printf("%d ", p);
	cnt[p] = id;
	R[id] = ha[0];
}
void build() {
	for(int i = 0; i < 2; i ++)
		if(ch[0][i]) q.push(ch[0][i]);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = 0; i < 2; i ++) {
			if(!ch[u][i]) ch[u][i] = ch[nxt[u]][i];
			else nxt[ch[u][i]] = ch[nxt[u]][i], q.push(ch[u][i]);
		}
	}
}
int vis[N];
void run(int id) { //printf("%d %d\n", L[id], R[id]);
	int p = 0;
	vis[0] = 1;
	for(int i = L[id]; i <= R[id]; i ++) {
		p = ch[p][ha[i]];//printf("*%d*", p);
		int pp = p, tt;
		while(pp) { //printf("%d ", pp);
			if(cnt[pp] && cnt[pp] != id) {
				g[id][cnt[pp]] = 1;// printf("%d --> %d\n", id, cnt[pp]);
				break;
			}
			pp = nxt[pp];
		}
		int haha = pp;
		pp = p;
		while(pp) { //printf("%d ", pp);
			if(cnt[pp] && cnt[pp] != id) {
				break;
			}
			tt = pp;
			pp = nxt[pp];
			nxt[tt] = haha;

		}
	}
}

int dis[1505], S, T, n;
int bfs() {
	memset(dis, -1, sizeof dis);
	dis[S] = 1;
	q.push(S);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = p[u]; i + 1; i = e[i].nxt) {
			int v = e[i].v;
			if(dis[v] == -1 && e[i].c) {
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	return dis[T] != -1;
}
int dfs(int u, int flow) { //printf("%d %d\n", u, flow);
	if(u == T) return flow;
	int ret = 0;
	for(int i = p[u]; i + 1; i = e[i].nxt) {
		int c = e[i].c, v = e[i].v;
		if(c && dis[v] == dis[u] + 1) {
			int tmp = dfs(v, min(flow, c));
			ret += tmp, flow -= tmp;
			e[i].c -= tmp, e[i^1].c += tmp;
			if(!flow) break;
		}
	}
	if(!ret) dis[u] = -1;
	return ret;
}
int Dinic() {
	int ret = 0;
	for(;bfs();) ret += dfs(S, INF);
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	init();
	cin >> n; T = 2 * n + 1;
	for(int i = 1; i <= n; i ++) cin >> st, insert(i);
	build();
	for(int i = 1; i <= n; i ++) run(i);
	for(int k = 1; k <= n; k ++)
		for(int i = 1; i <= n; i ++)
			for(int j = 1; j <= n; j ++)
				g[i][j] |= (g[i][k] & g[k][j]);
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			if(g[i][j] && i != j) add(i, j + n, 1);
	for(int i = 1; i <= n; i ++) add(S, i, 1), add(i + n, T, 1), vis[i + n] = 0;
	cout << n - Dinic() << endl;
	for(int i = 1; i <= n; i ++) if(dis[i] != -1 && dis[i + n] == -1) cout << i << ' ';
	return 0;
}


#include<bits/stdc++.h>
#define N 20000005
#define INF 2147483646 / 2
using namespace std;
struct edge {
	int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void insert(int u, int v, int c) {
	e[eid].v = v;
	e[eid].c = c;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
void add(int u, int v, int c) {
	insert(u, v, c);
	insert(v, u, 0);
}
int ch[N][2], cnt[N], tot, ys[1505], nxt[N], g[755][755];
string st[1505];
queue<int> q;
void insert(int id) {
	int p = 0, len = st[id].length();
	for(int i = 0; i < len; i ++) {
		if(!ch[p][st[id][i] - 'a']) ch[p][st[id][i] - 'a'] = ++ tot;
		p = ch[p][st[id][i] - 'a'];
	}
//	printf("%d ", p);
	cnt[p] = id;
	ys[id] = p;
}
void build() {
	for(int i = 0; i < 2; i ++)
		if(ch[0][i]) q.push(ch[0][i]);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = 0; i < 2; i ++) {
			if(!ch[u][i]) ch[u][i] = ch[nxt[u]][i];
			else nxt[ch[u][i]] = ch[nxt[u]][i], q.push(ch[u][i]);
		}
	}
}
int vis[N];
void run(int id) {
	int p = 0, len = st[id].length();
	vis[0] = 1;
	for(int i = 0; i < len; i ++) {//printf("*%d*", p);
		p = ch[p][st[id][i] - 'a'];
		int pp = p;
		while(!vis[pp]) {
			if(cnt[pp]) g[id][cnt[pp]] = 1;//, printf("%d --> %d\n", id, cnt[pp]);
			vis[pp] = 1; pp = nxt[pp];
		}
		if(cnt[pp]) g[id][cnt[pp]] = 1;//, printf("%d --> %d\n", id, cnt[pp]);
	}
}

int dis[1505], S, T, n;
int bfs() {
	memset(dis, -1, sizeof dis);
	dis[S] = 1;
	q.push(S);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = p[u]; i + 1; i = e[i].nxt) {
			int v = e[i].v;
			if(dis[v] == -1 && e[i].c) {
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	return dis[T] != -1;
}
int dfs(int u, int flow) { //printf("%d %d\n", u, flow);
	if(u == T) return flow;
	int ret = 0;
	for(int i = p[u]; i + 1; i = e[i].nxt) {
		int c = e[i].c, v = e[i].v;
		if(c && dis[v] == dis[u] + 1) {
			int tmp = dfs(v, min(flow, c));
			ret += tmp, flow -= tmp;
			e[i].c -= tmp, e[i^1].c += tmp;
			if(!flow) break;
		}
	}
	if(!ret) dis[u] = -1;
	return ret;
}
int Dinic() {
	int ret = 0;
	for(;bfs();) ret += dfs(S, INF);
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	init();
	cin >> n; T = 2 * n + 1;
	for(int i = 1; i <= n; i ++) cin >> st[i], insert(i);
	build();
	for(int i = 1; i <= n; i ++) run(i);
	for(int k = 1; k <= n; k ++)
		for(int i = 1; i <= n; i ++)
			for(int j = 1; j <= n; j ++)
				g[i][j] |= (g[i][k] & g[k][j]);
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			if(g[i][j] && i != j) add(i, j + n, INF);
	for(int i = 1; i <= n; i ++) add(S, i, 1), add(i + n, T, 1), vis[i + n] = 0;
	printf("%d\n", n - Dinic());
	for(int i = p[T]; i + 1; i = e[i].nxt) {
		int v = e[i].v;
		if(e[i ^ 1].c) {
			vis[v] = 1;
		}
	}
	for(int i = 1; i <= n; i ++) if(vis[i + n]) printf("%d ", i);
	return 0;
}


#include<bits/stdc++.h>
#define N 20000005
#define INF 2147483646 / 2
using namespace std;
struct edge {
	int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void insert(int u, int v, int c) {
	e[eid].v = v;
	e[eid].c = c;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
void add(int u, int v, int c) {
	insert(u, v, c);
	insert(v, u, 0);
}
int ch[N][2], cnt[N], tot, ys[1505], nxt[N], g[755][755], L[1505], R[1505], ha[N];
string st;
queue<int> q;
void insert(int id) {
	int p = 0, len = st.length();
	L[id] = ha[0] + 1;
	for(int i = 0; i < len; i ++) {
		ha[++ ha[0]] = st[i] - 'a';
		if(!ch[p][st[i] - 'a']) ch[p][st[i] - 'a'] = ++ tot;
		p = ch[p][st[i] - 'a'];
	}
//	printf("%d ", p);
	cnt[p] = id;
	R[id] = ha[0];
}
void build() {
	for(int i = 0; i < 2; i ++)
		if(ch[0][i]) q.push(ch[0][i]);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = 0; i < 2; i ++) {
			if(!ch[u][i]) ch[u][i] = ch[nxt[u]][i];
			else nxt[ch[u][i]] = ch[nxt[u]][i], q.push(ch[u][i]);
		}
	}
}
int vis[N];
void run(int id) { //printf("%d %d\n", L[id], R[id]);
	int p = 0;
	vis[0] = 1;
	for(int i = L[id]; i <= R[id]; i ++) {
		p = ch[p][ha[i]];//printf("*%d*", p);
		int pp = p, tt;
		while(pp) { //printf("%d ", pp);
			if(cnt[pp] && cnt[pp] != id) {
				g[id][cnt[pp]] = 1;// printf("%d --> %d\n", id, cnt[pp]);
				break;
			}
			pp = nxt[pp];
		}
		int haha = pp;
		pp = p;
		while(pp) { //printf("%d ", pp);
			if(cnt[pp] && cnt[pp] != id) {
				break;
			}
			tt = pp;
			pp = nxt[pp];
			nxt[tt] = haha;

		}
	}
}

int dis[1505], S, T, n;
int bfs() {
	memset(dis, -1, sizeof dis);
	dis[S] = 1;
	q.push(S);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = p[u]; i + 1; i = e[i].nxt) {
			int v = e[i].v;
			if(dis[v] == -1 && e[i].c) {
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	return dis[T] != -1;
}
int dfs(int u, int flow) { //printf("%d %d\n", u, flow);
	if(u == T) return flow;
	int ret = 0;
	for(int i = p[u]; i + 1; i = e[i].nxt) {
		int c = e[i].c, v = e[i].v;
		if(c && dis[v] == dis[u] + 1) {
			int tmp = dfs(v, min(flow, c));
			ret += tmp, flow -= tmp;
			e[i].c -= tmp, e[i^1].c += tmp;
			if(!flow) break;
		}
	}
	if(!ret) dis[u] = -1;
	return ret;
}
int Dinic() {
	int ret = 0;
	for(;bfs();) ret += dfs(S, INF);
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	init();
	cin >> n; T = 2 * n + 1;
	for(int i = 1; i <= n; i ++) cin >> st, insert(i);
	build();
	for(int i = 1; i <= n; i ++) run(i);
	for(int k = 1; k <= n; k ++)
		for(int i = 1; i <= n; i ++)
			for(int j = 1; j <= n; j ++)
				g[i][j] |= (g[i][k] & g[k][j]);
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			if(g[i][j] && i != j) add(i, j + n, 1);
	for(int i = 1; i <= n; i ++) add(S, i, 1), add(i + n, T, 1), vis[i + n] = 0;
	cout << n - Dinic() << endl;
	for(int i = 1; i <= n; i ++) if(dis[i] != -1 && dis[i + n] == -1) cout << i << ' ';
	return 0;
}


#include<bits/stdc++.h>
#define N 10000005
#define INF 2147483646 / 2
using namespace std;
struct edge {
	int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void insert(int u, int v, int c) {
	e[eid].v = v;
	e[eid].c = c;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
void add(int u, int v, int c) {
	insert(u, v, c);
	insert(v, u, 0);
}
int ch[N][2], cnt[N], tot, ys[1505], nxt[N], g[755][755], L[1505], R[1505], ha[N];
string st;
queue<int> q;
void insert(int id) {
	int p = 0, len = st.length();
	L[id] = ha[0] + 1;
	for(int i = 0; i < len; i ++) {
		ha[++ ha[0]] = st[i] - 'a';
		if(!ch[p][st[i] - 'a']) ch[p][st[i] - 'a'] = ++ tot;
		p = ch[p][st[i] - 'a'];
	}
//	printf("%d ", p);
	cnt[p] = id;
	R[id] = ha[0];
}
void build() {
	for(int i = 0; i < 2; i ++)
		if(ch[0][i]) q.push(ch[0][i]);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = 0; i < 2; i ++) {
			if(!ch[u][i]) ch[u][i] = ch[nxt[u]][i];
			else nxt[ch[u][i]] = ch[nxt[u]][i], q.push(ch[u][i]);
		}
	}
}
int vis[N];
void run(int id) {
	int p = 0;
	vis[0] = 1;
	for(int i = L[id]; i <= R[id]; i ++) {//printf("*%d*", p);
		p = ch[p][ha[i]];
		int pp = p;
		while(!vis[pp]) {
			if(cnt[pp]) g[id][cnt[pp]] = 1;//, printf("%d --> %d\n", id, cnt[pp]);
			vis[pp] = 1; pp = nxt[pp];
		}
		if(cnt[pp]) g[id][cnt[pp]] = 1;//, printf("%d --> %d\n", id, cnt[pp]);
	}
}

int dis[1505], S, T, n;
int bfs() {
	memset(dis, -1, sizeof dis);
	dis[S] = 1;
	q.push(S);
	while(q.size()) {
		int u = q.front(); q.pop();
		for(int i = p[u]; i + 1; i = e[i].nxt) {
			int v = e[i].v;
			if(dis[v] == -1 && e[i].c) {
				dis[v] = dis[u] + 1;
				q.push(v);
			}
		}
	}
	return dis[T] != -1;
}
int dfs(int u, int flow) { //printf("%d %d\n", u, flow);
	if(u == T) return flow;
	int ret = 0;
	for(int i = p[u]; i + 1; i = e[i].nxt) {
		int c = e[i].c, v = e[i].v;
		if(c && dis[v] == dis[u] + 1) {
			int tmp = dfs(v, min(flow, c));
			ret += tmp, flow -= tmp;
			e[i].c -= tmp, e[i^1].c += tmp;
			if(!flow) break;
		}
	}
	if(!ret) dis[u] = -1;
	return ret;
}
int Dinic() {
	int ret = 0;
	for(;bfs();) ret += dfs(S, INF);
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	init();
	cin >> n; T = 2 * n + 1;
	for(int i = 1; i <= n; i ++) cin >> st, insert(i);
	build();
	for(int i = 1; i <= n; i ++) run(i);
	for(int k = 1; k <= n; k ++)
		for(int i = 1; i <= n; i ++)
			for(int j = 1; j <= n; j ++)
				g[i][j] |= (g[i][k] & g[k][j]);
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			if(g[i][j] && i != j) add(i, j + n, INF);
	for(int i = 1; i <= n; i ++) add(S, i, 1), add(i + n, T, 1), vis[i + n] = 0;
	cout << n - Dinic() << endl;
	for(int i = p[T]; i + 1; i = e[i].nxt) {
		int v = e[i].v;
		if(e[i ^ 1].c) {
			vis[v] = 1;
		}
	}
	for(int i = 1; i <= n; i ++) if(vis[i + n]) cout << i << ' ';
	return 0;
}