#include<bits/stdc++.h>

using namespace std;
#define ll long long

const int inf = 1e9;
struct MaxFlow{
	struct edge{ int to, f, id;};
	bool gap;
	int n, S, T;
	vector<int> cur, cnt, d;
	vector<vector<edge>> e;
	void ext(int x){ if(++x>n) e.resize(n=x);}
	inline void add(int x, int y, int z){
		ext(x), ext(y);
		e[x].push_back((edge){y, z, (int)e[y].size()});
		e[y].push_back((edge){x, 0, (int)e[x].size()-1});
	}
	int sap(int u, int flow){
		if(u==T || !flow) return flow;
		int now=0;
		for(unsigned i=cur[u]; i<e[u].size(); ++i){
			edge &v=e[u][i];
			if(d[v.to]+1==d[u]){
				int tmp=sap(v.to, min(flow-now, (int)v.f));
				v.f-=tmp, now+=tmp, e[v.to][v.id].f+=tmp, cur[u]=i;
				if(gap) return now;
			}
			if(now==flow) return flow;
		}
		cur[u]=0;
		if(!--cnt[d[u]]) gap=1;
		else ++cnt[++d[u]];
		return now;
	}
	int solve(int s, int t){
		cur.resize(n), cnt.resize(n), d.resize(n);
		S=s, T=t, cnt[0]=n-1, gap=0;
		int ans=0;
		while(!gap && d[S]<n) ans+=sap(s, inf);
		return ans;
	}
} wish;
const int N = 755, M = 10000005;
int n, t, cnt, ans, pos[N], f[M], fa[M], q[M], fail[M], ch[M][2];
bool a[N][N], ban[M];
char s[M];
int main() {
	scanf("%d", &n);
	cnt=1;
	for(int i=1; i<=n; ++i){
		scanf("%s", s);
		int &p=pos[i];
		p=1;
		for(int j=0; s[j]; ++j){
			int &x=ch[p][s[j]-'a'];
			fa[x?x:x=++cnt]=p, p=x;
		}
		if(f[p]) ban[i]=1, ++ans; else f[p]=i;
	}
	q[t=1]=1;
	for(int i=1; i<=t; ++i){
		int u=q[i];
		if(!f[u]) f[u]=f[fail[u]];
		for(int i=0; i<2; ++i) if(ch[u][i]){
			int x=fail[u];
			while(x && !ch[x][i]) x=fail[x];
			fail[ch[u][i]]=x?ch[x][i]:1;
			q[++t]=ch[u][i];
		}
	}
	for(int i=1; i<=n; ++i){
		a[i][f[fail[pos[i]]]]=1;
		for(int j=fa[pos[i]]; j; j=fa[j]) a[i][f[j]]=1;
	}
	for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j)
		a[i][j]|=a[i][k] && a[k][j];
	for(int i=1; i<=n; ++i) if(!ban[i])
		wish.add(n*2+1, i, 1), wish.add(i+n, n*2+2, 1);
	for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) if(a[i][j])
		wish.add(i, j+n, inf);
	printf("%d\n", n-ans-wish.solve(n*2+1, n*2+2));
	for(int i=1; i<=n; ++i) if(!ban[i] && !wish.e[i][0].f)
		printf("%d ", i);
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
#define ll long long

const int N = 755, M = 10000005;
int n, t, cnt, pos[N], p[N], f[M], fa[M], q[M], fail[M], ch[M][2];
bool vis[N], mat[N], a[N][N];
char s[M];
bool match(int x){
	for(int i=1; i<=n; ++i) if(!vis[i] && a[x][i]){
		vis[i]=1;
		if(!p[i] || match(p[i])) return p[i]=x, mat[x]=1;
	}
	return 0;
}
int main() {
	scanf("%d", &n);
	cnt=1;
	for(int i=1; i<=n; ++i){
		scanf("%s", s);
		int &p=pos[i];
		p=1;
		for(int j=0; s[j]; ++j){
			int &x=ch[p][s[j]-'a'];
			fa[x?x:x=++cnt]=p, p=x;
		}
		f[p]=i;
	}
	q[t=1]=1;
	for(int i=1; i<=t; ++i){
		int u=q[i];
		if(!f[u]) f[u]=f[fail[u]];
		for(int i=0; i<2; ++i) if(ch[u][i]){
			int x=fail[u];
			while(x && !ch[x][i]) x=fail[x];
			fail[ch[u][i]]=x?ch[x][i]:1;
			q[++t]=ch[u][i];
		}
	}
	for(int i=1; i<=n; ++i){
		a[i][f[fail[pos[i]]]]=1;
		for(int j=fa[pos[i]]; j; j=fa[j]) a[i][f[j]]=1;
	}
	for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j)
		a[i][j]|=a[i][k] && a[k][j];
	for(int i=1; i<=n; ++i) match(i), memset(vis, 0, sizeof vis);
	t=0;
	for(int i=1; i<=n; ++i) if(!mat[i]) q[++t]=i;
	printf("%d\n", t);
	for(int i=1; i<=t; ++i) for(int j=1; j<=n; ++j) if(a[q[i]][j] && !vis[j]){
		vis[j]=1;
		if(mat[p[j]]) q[++t]=p[j], mat[p[j]]=0;
	}
	for(int i=1; i<=n; ++i) if(!mat[i] && !vis[i]) printf("%d ", i);
	for(int i=1; i<=n; ++i) assert(!(mat[i] && vis[i]));
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
#define ll long long

const int N = 755, M = 10000005;
int n, t, cnt, cans, pos[N], ans[N], f[M], fa[M], q[M], fail[M], ch[M][2];
char s[M];
int main() {
	scanf("%d", &n);
	cnt=1;
	for(int i=1; i<=n; ++i){
		scanf("%s", s);
		int &p=pos[i];
		p=1;
		for(int j=0; s[j]; ++j){
			int &x=ch[p][s[j]-'a'];
			fa[x?x:x=++cnt]=p, p=x;
		}
		f[p]=1;
	}
	q[t=1]=1;
	for(int i=1; i<=t; ++i){
		int u=q[i];
		f[u]+=f[fail[u]];
		for(int i=0; i<2; ++i) if(ch[u][i]){
			int x=fail[u];
			while(x && !ch[x][i]) x=fail[x];
			fail[ch[u][i]]=x?ch[x][i]:1;
			q[++t]=ch[u][i];
		}
	}
	for(int i=1; i<=n; ++i){
		bool ok=0;
		for(int j=fa[pos[i]]; j>1; j=fa[j]) ok|=f[j];
		if(!ok && f[pos[i]]-f[fail[pos[i]]]==1) ans[++cans]=i;
	}
	printf("%d\n", cans);
	for(int i=1; i<=cans; ++i) printf("%d%c", ans[i], " \n"[i==cans]);
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
#define ll long long

const int N = 755, M = 10000005;
int n, t, cnt, ans, pos[N], p[N], f[M], fa[M], q[M], fail[M], ch[M][2];
bool vis[N], mat[N], a[N][N], ban[M];
char s[M];
bool match(int x){
	for(int i=1; i<=n; ++i) if(!vis[i] && a[x][i]){
		vis[i]=1;
		if(!p[i] || match(p[i])) return p[i]=x, mat[i]=1;
	}
	return 0;
}
int main() {
	scanf("%d", &n);
	cnt=1;
	for(int i=1; i<=n; ++i){
		scanf("%s", s);
		int &p=pos[i];
		p=1;
		for(int j=0; s[j]; ++j){
			int &x=ch[p][s[j]-'a'];
			fa[x?x:x=++cnt]=p, p=x;
		}
		if(f[p]) ban[i]=1, ++ans; else f[p]=i;
	}
	q[t=1]=1;
	for(int i=1; i<=t; ++i){
		int u=q[i];
		if(!f[u]) f[u]=f[fail[u]];
		for(int i=0; i<2; ++i) if(ch[u][i]){
			int x=fail[u];
			while(x && !ch[x][i]) x=fail[x];
			fail[ch[u][i]]=x?ch[x][i]:1;
			q[++t]=ch[u][i];
		}
	}
	for(int i=1; i<=n; ++i){
		a[i][f[fail[pos[i]]]]=1;
		for(int j=fa[pos[i]]; j; j=fa[j]) a[i][f[j]]=1;
	}
	for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j)
		a[i][j]|=a[i][k] && a[k][j];
	for(int i=1; i<=n; ++i) ans+=match(i), memset(vis, 0, sizeof vis);
	for(int i=1; i<=n; ++i) if(!mat[i]) q[++t]=i;
	for(int i=1; i<=t; ++i){
		int x=q[i];
		for(int j=1; j<=n; ++j) if(a[x][j] && !vis[j]){
			vis[j]=1;
			if(mat[p[j]]) q[++t]=p[j], mat[p[j]]=0;
		}
	}
	printf("%d\n", n-ans);
	for(int i=1; i<=n; ++i) if(!ban[i] && !mat[i] && !vis[i]) printf("%d ", i);
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
#define ll long long

const int N = 755, M = 10000005;
int n, t, cnt, ans, pos[N], p[N], f[M], fa[M], q[M], fail[M], ch[M][2];
bool vis[N], mat[N], a[N][N], ban[M];
char s[M];
bool match(int x){
	for(int i=1; i<=n; ++i) if(!vis[i] && a[x][i]){
		vis[i]=1;
		if(!p[i] || match(p[i])) return p[i]=x, mat[i]=1;
	}
	return 0;
}
int main() {
	scanf("%d", &n);
	cnt=1;
	for(int i=1; i<=n; ++i){
		scanf("%s", s);
		int &p=pos[i];
		p=1;
		for(int j=0; s[j]; ++j){
			int &x=ch[p][s[j]-'a'];
			fa[x?x:x=++cnt]=p, p=x;
		}
		if(f[p]) ban[i]=1, ++ans; else f[p]=i;
	}
	q[t=1]=1;
	for(int i=1; i<=t; ++i){
		int u=q[i];
		if(!f[u]) f[u]=f[fail[u]];
		for(int i=0; i<2; ++i) if(ch[u][i]){
			int x=fail[u];
			while(x && !ch[x][i]) x=fail[x];
			fail[ch[u][i]]=x?ch[x][i]:1;
			q[++t]=ch[u][i];
		}
	}
	for(int i=1; i<=n; ++i){
		a[i][f[fail[pos[i]]]]=1;
		for(int j=fa[pos[i]]; j; j=fa[j]) a[i][f[j]]=1;
	}
	for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j)
		a[i][j]|=a[i][k] && a[k][j];
	for(int i=1; i<=n; ++i) ans+=match(i), memset(vis, 0, sizeof vis);
	t=0;
	for(int i=1; i<=n; ++i) if(!mat[i]) q[++t]=i;
	for(int i=1; i<=t; ++i){
		int x=q[i];
		for(int j=1; j<=n; ++j) if(a[x][j] && !vis[j]){
			vis[j]=1;
			if(mat[p[j]]) q[++t]=p[j], mat[p[j]]=0;
		}
	}
	printf("%d\n", n-ans);
	for(int i=1; i<=n; ++i) if(!ban[i] && !mat[i] && !vis[i]) printf("%d ", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAXN 1010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;
vector<int> st[MAXN];

vector<int> gao() {
	vector<int> ans;
	for (int i = 1;i <= ns;i++) {
		for (int x : st[i]) {
			if (removed[x]) continue;
			bool flag = 0;
			for (int j = i + 1;j <= ns;j++) {
				bool flag2 = 0;
				for (int k : st[j])
					if (!g[x][k] && !g[k][x])
						flag2 = 1;
				if (!flag2) {
					flag = 1;
					break;
				}
			}
			if (flag) continue;
			ans.push_back(x);
			for (int j = 1;j <= n;j++)
				if (g[x][j] || g[j][x])
					removed[j] = 1;
		}
	}
	return ans;
}

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXN];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void find(int x, int cur) {
		st[cur].push_back(x);
		visit[x] = 1;
		for (int i = g[x * 2 - 1];~i;i = e[i].next)
			if (e[i].to < S && !e[i].w)
				find(e[i].to / 2, cur);
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	for (int i = 1;i <= n;i++)
		if (Graph::check(i)) {
			ns++;
			Graph::find(i, ns);
		}
	vector<int> ans = gao();
	printf("%d\n", ans.size());
	for(int i:ans) printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 10000100
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
				if(d==2 && !r[i])
					puts("zjtsb");
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
				if(d==2 && !r[i])
					puts("zjtsb");
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++)
			if(r[i])
				assert(r[r[i]]==i);
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;
vector<int> st[MAXN];

vector<int> gao() {
	vector<int> ans;
	for (int i = 1;i <= ns;i++) {
		for (int x : st[i]) {
			if (removed[x]) continue;
			bool flag = 0;
			for (int j = i + 1;j <= ns;j++) {
				bool flag2 = 0;
				for (int k : st[j])
					if (!removed[k] && !g[x][k] && !g[k][x])
						flag2 = 1;
				if (!flag2) {
					flag = 1;
					break;
				}
			}
			if (flag) continue;
			ans.push_back(x);
			for (int j = 1;j <= n;j++)
				if (g[x][j] || g[j][x])
					removed[j] = 1;
		}
	}
	return ans;
}

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i] && !visit[i])
				dfs2(i, 3-d);
	}

	void gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++)
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	Graph::gao();
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
				if(d==2 && !r[i])
					puts("zjtsb");
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++)
			if(visit[i]==1)
				cnt++;
		return cnt;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i] && !visit[i])
				dfs2(i, 3-d);
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++)
			if(visit[i]==1)
				cnt++;
		return cnt;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 10000100
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		if(d==1){
			dfs2(r[x], 2);
			return;
		}
		for(int i=1;i<S;i++)
			if(e2[x][i]  && !visit[i])
				dfs2(i, 3-d);
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 1);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 1010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;
vector<int> st[MAXN];

vector<int> gao() {
	vector<int> ans;
	for (int i = 1;i <= ns;i++) {
		for (int x : st[i]) {
			if (removed[x]) continue;
			bool flag = 0;
			for (int j = i + 1;j <= ns;j++) {
				bool flag2 = 0;
				for (int k : st[j])
					if (!removed[k] && !g[x][k] && !g[k][x])
						flag2 = 1;
				if (!flag2) {
					flag = 1;
					break;
				}
			}
			if (flag) continue;
			ans.push_back(x);
			for (int j = 1;j <= n;j++)
				if (g[x][j] || g[j][x])
					removed[j] = 1;
		}
	}
	return ans;
}

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void find(int x, int cur) {
		st[cur].push_back(x);
		visit[x] = 1;
		for (int i = g[x * 2 - 1];~i;i = e[i].next)
			if (e[i].to < S && !e[i].w)
				find(e[i].to / 2, cur);
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	for (int i = 1;i <= n;i++)
		if (Graph::check(i)) {
			ns++;
			Graph::find(i, ns);
		}
	vector<int> ans = gao();
	printf("%d\n", n-flow);
	for(int i:ans) printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 1010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;
vector<int> st[MAXN];

vector<int> gao() {
	vector<int> ans;
	for (int i = 1;i <= ns;i++) {
		for (int x : st[i]) {
			if (removed[x]) continue;
			bool flag = 0;
			for (int j = i + 1;j <= ns;j++) {
				bool flag2 = 0;
				for (int k : st[j])
					if (!g[x][k] && !g[k][x])
						flag2 = 1;
				if (!flag2) {
					flag = 1;
					break;
				}
			}
			if (flag) continue;
			ans.push_back(x);
			for (int j = 1;j <= n;j++)
				if (g[x][j] || g[j][x])
					removed[j] = 1;
		}
	}
	return ans;
}

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void find(int x, int cur) {
		st[cur].push_back(x);
		visit[x] = 1;
		for (int i = g[x * 2 - 1];~i;i = e[i].next)
			if (e[i].to < S && !e[i].w)
				find(e[i].to / 2, cur);
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	for (int i = 1;i <= n;i++)
		if (Graph::check(i)) {
			ns++;
			Graph::find(i, ns);
		}
	vector<int> ans = gao();
	printf("%d\n", n-flow);
	for(int i:ans) printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAXN 1010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;
vector<int> st[MAXN];

vector<int> gao() {
	vector<int> ans;
	for (int i = 1;i <= ns;i++) {
		for (int x : st[i]) {
			if (removed[x]) continue;
			bool flag = 0;
			for (int j = i + 1;j <= ns;j++) {
				bool flag2 = 0;
				for (int k : st[j])
					if (!g[x][k] && !g[k][x])
						flag2 = 1;
				if (!flag2) {
					flag = 1;
					break;
				}
			}
			if (flag) continue;
			ans.push_back(x);
			for (int j = 1;j <= n;j++)
				if (g[x][j] || g[j][x])
					removed[j] = 1;
		}
	}
	return ans;
}

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void find(int x, int cur) {
		st[cur].push_back(x);
		visit[x] = 1;
		for (int i = g[x * 2 - 1];~i;i = e[i].next)
			if (e[i].to < S && !e[i].w)
				find(e[i].to / 2, cur);
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	for (int i = 1;i <= n;i++)
		if (Graph::check(i)) {
			ns++;
			Graph::find(i, ns);
		}
	vector<int> ans = gao();
	printf("%d\n", ans.size());
	for(int i:ans) printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++)
			if(r[i])
				cnt++;
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i]){
				cnt++;
				if(visit[r[i]]==visit[i])
					puts("d2");
			}
			else if(visit[i]==1)
				puts("d1");
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 10000100
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
				if(d==2 && !r[i])
					puts("zjtsb");
			}
	}

	void dfs3(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs3(i, 3-d);
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs3(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 1010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;
vector<int> st[MAXN];

vector<int> gao() {
	vector<int> ans;
	for (int i = 1;i <= ns;i++) {
		for (int x : st[i]) {
			if (removed[x]) continue;
			bool flag = 0;
			for (int j = i + 1;j <= ns;j++) {
				bool flag2 = 0;
				for (int k : st[j])
					if (!g[x][k] && !g[k][x])
						flag2 = 1;
				if (!flag2) {
					flag = 1;
					break;
				}
			}
			if (flag) continue;
			ans.push_back(x);
			for (int j = 1;j <= n;j++)
				if (g[x][j] || g[j][x])
					removed[j] = 1;
		}
	}
	return ans;
}

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void find(int x, int cur) {
		st[cur].push_back(x);
		visit[x] = 1;
		for (int i = g[x * 2 - 1];~i;i = e[i].next)
			if (e[i].to < S && !e[i].w)
				find(e[i].to / 2, cur);
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	for (int i = 1;i <= n;i++)
		if (Graph::check(i)) {
			ns++;
			Graph::find(i, ns);
		}
	vector<int> ans = gao();
	assert(ans.size()==n-flow);
	printf("%d\n", ans.size());
	for(int i:ans) printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 10000100
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			for(int j=1;j<S;j++)
				if(e2[i][j])
					assert((i+j)%2);
			if(r[i])
				assert(r[r[i]]==i);
		}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 1000010
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i] && !visit[i])
				dfs2(i, 3-d);
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++)
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		for(int i=1;i<S;i++)
			if(!visit[i])
				dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++)
			if(visit[i]==1)
				cnt++;
		return cnt;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	assert(Graph::gao()==flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <queue>
#define MAXN 2010
#define MAXM 10000100
#define MAXP 10000100

using namespace std;

int n, ns;
int ls[MAXN], *pt[MAXN];
int g[MAXN][MAXN];
int removed[MAXN];
int p[MAXN][2], np;

namespace ACAM {
	int size=1;
	int ch[MAXP][2],pre[MAXP],last[MAXP];
	bool tag[MAXP];
	int visit[MAXP];

	void build() {
		static int q[MAXP];
		int head = 1, tail = 0;
		q[0] = 1;
		if (!ch[1][0]) ch[1][0] = 1;
		else q[++tail] = ch[1][0],pre[ch[1][0]] = 1;
		if (!ch[1][1]) ch[1][1] = 1;
		else q[++tail] = ch[1][1],pre[ch[1][1]] = 1;
		while (head <= tail) {
			int x = q[head++];
			last[x] = tag[x] ? x : last[pre[x]];
			if (!ch[x][0]) ch[x][0] = ch[pre[x]][0];
			else q[++tail] = ch[x][0], pre[ch[x][0]] = ch[pre[x]][0];
			if (!ch[x][1]) ch[x][1] = ch[pre[x]][1];
			else q[++tail] = ch[x][1], pre[ch[x][1]] = ch[pre[x]][1];
		}
	}
}

namespace Graph {
	struct edge {
		int to, next, w;
		edge(int _to = 0, int _next = 0, int _w = 0) :to(_to), next(_next), w(_w) {}
	}e[MAXM];

	int n, S, T;
	int g[MAXN], ne;
	int level[MAXN], cur[MAXN];
	int visit[MAXN];
	int r[MAXN],e2[MAXN][MAXN];
	int tag[MAXN];

	void addEdge(int u, int v, int w) {
		e[ne] = edge(v, g[u], w);
		g[u] = ne++;
		e[ne] = edge(u, g[v], 0);
		g[v] = ne++;
	}

	bool bfs() {
		for (int i = 1;i <= n;i++)
			cur[i] = g[i], level[i] = -1;
		static queue<int> Q;
		Q.push(S);
		level[S] = 0;
		while (!Q.empty()) {
			int x = Q.front(); Q.pop();
			for (int i = g[x];~i;i = e[i].next)
				if (e[i].w && level[e[i].to] == -1) {
					level[e[i].to] = level[x] + 1;
					Q.push(e[i].to);
				}
		}
		return level[T] != -1;
	}

	int dfs(int x, int delta) {
		if (x == T) return delta;
		int res = 0;
		for (int &i = cur[x];~i;i = e[i].next)
			if (e[i].w && level[e[i].to] == level[x] + 1) {
				int temp = dfs(e[i].to, min(delta, e[i].w));
				res += temp;
				delta -= temp;
				e[i].w -= temp;
				e[i ^ 1].w += temp;
				if (!delta) return res;
			}
		return res;
	}

	bool check(int x) {
		for (int i = g[x * 2];~i;i = e[i].next)
			if (e[i].to < S && e[i].w)
				return 0;
		return 1;
	}

	void dfs2(int x, int d){
		visit[x]=d;
		for(int i=1;i<S;i++)
			if(e2[x][i]){
				if(!visit[i])
					dfs2(i, 3-d);
				else assert(visit[i]==3-d);
				if(d==2 && !r[i])
					puts("zjtsb");
			}
	}

	int gao(){
		for(int i=1;i<S;i+=2)
			for(int j=g[i];~j;j=e[j].next)
				if(e[j].to<S){
					e2[i][e[j].to]=e2[e[j].to][i]=1;
					if(!e[j].w) r[i]=e[j].to, r[e[j].to]=i;
				}
		for(int i=1;i<S;i++){
			if(!visit[i] && !r[i])
				dfs2(i, 2);
		}
		// for(int i=1;i<S;i++)
		// 	if(!visit[i])
		// 		dfs2(i, 2);
		int cnt=0;
		for(int i=1;i<S;i++){
			if(r[i])
				cnt++;
		}
		return cnt/2;
	}
}

bool cmp(int x, int y) {
	return pt[x][0] < pt[y][0];
}

int main() {
#ifdef DEBUG
	freopen("in.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) {
		int x = 1;
		char c;
		static int tp[MAXP];
		int len = 0;
		while ((c = getchar()) != 'a' && c != 'b');
		do{
			if (!ACAM::ch[x][c - 'a'])
				ACAM::ch[x][c - 'a'] = ++ACAM::size;
			tp[++len] = x = ACAM::ch[x][c - 'a'];
		} while ((c = getchar()) == 'a' || c == 'b');
		pt[i] = new int[len + 1];
		pt[i][0] = len;
		for (int j = 1;j <= len;j++) pt[i][j] = tp[j];
		ACAM::tag[x] = 1;
		ls[i] = i;
	}
	sort(ls + 1, ls + n + 1, cmp);
	ACAM::build();
	for (int i = 1;i <= n;i++) p[i][0] = ++np, p[i][1] = ++np;
	Graph::S = ++np; Graph::n = Graph::T = ++np;
	memset(Graph::g, -1, sizeof Graph::g);
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= pt[i][0];j++)
			if (ACAM::last[pt[i][j]])
				ACAM::visit[ACAM::last[pt[i][j]]] = i;
		for (int j = n;j >= 1;j--) {
			int x = ls[j], y = pt[x][pt[x][0]];
			if (ACAM::visit[y] == i) {
				if (i != x) {
					Graph::addEdge(p[i][0], p[x][1], 1);
					g[i][x] = 1;
				}
				if (ACAM::last[ACAM::pre[y]]) ACAM::visit[ACAM::last[ACAM::pre[y]]] = i;
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		Graph::addEdge(Graph::S, p[i][0], 1);
		Graph::addEdge(p[i][1], Graph::T, 1);
	}
	int flow = 0;
	while (Graph::bfs())
		flow += Graph::dfs(Graph::S, 1 << 30);
	int temp = Graph::gao();
	if(temp!=flow) printf("%d %d\n", temp, flow);
	printf("%d\n", n-flow);
	for(int i=1;i<=n;i++)
		if(Graph::visit[i*2-1]==2 && Graph::visit[i*2]==2)
			printf("%d\n", i);
	return 0;
}


#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
using namespace std;
// #define TRACE
#ifdef TRACE
#include "../trace.h"
#else
#define trace(args...)
#endif
typedef long long ll;
typedef long double ld;
typedef vector<ll> vl;		typedef vector<int> vi;
typedef vector<vl> vvl;	  	typedef vector<vi> vvi;
typedef pair<ll, ll> pll;	typedef pair<int, int> pii;
typedef vector<pll> vpl;	typedef vector<pii> vpi;
typedef vector<vpl> vvpl;	typedef vector<vpi> vvpi;
#define S second
#define F first
#define V vector
#define MP make_pair
#define PB push_back
#define EB emplace_back
#define POB pop_back
#define PF push_front
#define POF pop_front
#define sz(x) (int)x.size()
#define f(i,j,k,l) for(int i =(int)j; i!=(int)k; i = i + l)
#define INP(v,n) f(i,0,n,1) cin>>v[i];
#define OUT(v,n) f(i,0,n,1){ cout<<v[i]<<" ";}cout<<endl;
#define endl '\n'
#define all(v) v.begin(), v.end()
const ll mod = 998244353;
const int inf = 1e9;
bool vis[1700];
int in[760];
bool adj[760][760];
bool trans[760][760];
bool rep[760];
int tot = 0;

int fin(int i){
	if(in[i] != i){
		in[i] = fin(in[i]);
	}
	return in[i];
}

struct edkarp{
	vector<vector<int>> cap;
	vector<vector<int>> eds;
	int n,m;
	void init(int _n){
		n = _n;
		m = (n-2)/2;
		cap.assign(n,vector<int>(n,0));
		eds.assign(n,vector<int>(0));
	}

	void add(int u, int v, int c){
		eds[u].emplace_back(v);
		eds[v].emplace_back(u);
		cap[u][v] = c;
	}
	int bfs(int st, int tar, vector<int> &p){//p must already be of req. size
		fill(p.begin(), p.end(), -1);
		p[st] = -2;
		queue<pair<int,int>> q;
		q.push(MP(st,inf));
		while(!q.empty()){
			int i = q.front().F, flow = q.front().S;
			q.pop();
			for(auto &x : eds[i]){
				if(p[x] == -1 && cap[i][x]){
					p[x] = i;
					int nf = min(flow, cap[i][x]);
					if(x == tar){
						return nf;
					}
					q.push(MP(x, nf));
				}
			}
		}
		return 0;
	}

	int maxflow(int st, int tar){
		// if there is need to upgrade number of nodes in graph
		vector<int> p(n);//num is the number of nodes
		int flow = 0;
		int nf;//new flow

		while(nf = bfs(st,tar,p)){
			flow += nf;
			int cr = tar;
			while(cr != st){
				cap[p[cr]][cr] -= nf;
				cap[cr][p[cr]] += nf;
				cr = p[cr];
			}
		}

		return flow;
	}
	void dfs(int i){
		trace(i);
		vis[i] = 1;
		for(auto &x : eds[i])if(!vis[x] && x != 0 && x != n-1){
			if(cap[i][x])dfs(x);
		}
	}
	void sten(){
		fill(vis,vis + n,false);
		for(int i = 1; i <=m ;i++){
			for(int j = 1; j<= m; j++){
				if(cap[j+m][i]){
					in[i] = 1;
					break;
				}
			}
		}
		for(int i =1; i<=m; i++){
			if(in[i] == 0 && !vis[i]) dfs(i);
		}
	}
};

const int K = 2;//alphabet size
struct node {
	node* ch[K];
	node* p;
	node* nt;//next terminal
	node* sl;
	int ind = -1;
	bool pch; //suffix_link
	node(node* p = NULL, bool b = false): p(p), pch(b) {
		sl = NULL; ch[0] = NULL; ch[1] = NULL;
		nt = NULL;
	}
};

template<class node>
struct ahoc {
	node* root = NULL;
	edkarp fl;
	ahoc() {
		root = new node();
	}
	void init(int n){
		fl.init(n);
	}
	inline int getin(char c) { //modify accordingly
		return c - 'a';
	}
	void ins(string const& s, int i) {
		node* cr = root;
		for (char c : s) {
			int z = getin(c);
			if (!cr->ch[z]) {
				cr->ch[z] = new node(cr, c == 'b');
			}
			cr = cr->ch[z];
		}
		if(cr->ind == -1) cr->ind = i;
		else rep[i] = 1, tot++;
	}

	void trav(string const& s, int i) {
		node* cr = root;
		for (char c : s) {
			if(cr->ind != -1){
				adj[cr->ind][i] =trans[cr->ind][i] = true;
			}
			int z = getin(c);
			cr = cr->ch[z];
			node* tmp = get_nt(cr);
			if(tmp != root) adj[tmp->ind][i] =trans[tmp->ind][i] = true;
		}
	}

	node* get_sl(node* cr) {
		if (!cr->sl) {
			if (cr == root || cr->p == root)
				cr->sl = root;
			else
				cr->sl = go(get_sl(cr->p), cr->pch);
		}
		return cr->sl;
	}

	node* go(node* cr, bool c) {
		int z = c;
		if (!cr->ch[z]) {
			if (cr == root)
				cr->ch[z] = root;
			else
				cr->ch[z] = go(get_sl(cr), c);
		}
		return cr->ch[z];
	}

	node* get_nt(node* cr) {
		if (!cr->nt) {
			node* tmp = get_sl(cr);
			if (tmp == root) {
				cr->nt = root;
			} else if (tmp->ind == -1) {
				cr->nt = get_nt(tmp);
			} else {
				cr->nt = tmp;
			}
		}
		return cr->nt;
	}
};

string s[760];
int n;
ahoc<node> fo;

void dfs(int i){
	vis[i] = 1;
	f(j,1,n+1,1){
		if(j == i) continue;
		if(!trans[i][j]) continue;
		if(!vis[j]) dfs(j);
		f(k,1,n+1,1){
			if(k == i || k == j) continue;
			if(!trans[j][k]) continue;
			trans[i][k] = 1;
		}
	}
}

void solve() {
	cin >> n;
	f(i, 1, n + 1, 1) {
		cin >> s[i];
	}
	f(i, 1, n + 1, 1) {
		fo.ins(s[i], i);
	}
	fo.init(2*n+2);
	f(i, 1, n + 1, 1) {
		fo.trav(s[i], i);
		fo.fl.add(0,i,1);
		fo.fl.add(n+i,2*n+1,1);
	}
	for(int i = 1; i <= n; i++){
		if(!vis[i]) dfs(i);
	}
	f(i,1,n+1,1){
		f(j,1,n+1,1){
			if(i == j) continue;
			if(trans[i][j]){
				fo.fl.add(i,j+n,1);
			}
		}
	}
	cout<<n - tot- fo.fl.maxflow(0,2*n+1)<<endl;
	fo.fl.sten();
	for(int i = 1; i<= n; i++){
		if(vis[i] && !vis[i+n] && !rep[i]) cout<<i<<" ";
	}cout<<endl;
}

int main() {
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t = 1;
	//cin>>t;
	while (t--) {
		solve();
	}
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef int LL;
const LL N = 10000005,NN = 755,M = 5005;

LL ch[2][N],fail[N],rt = 0,tot = 0;
LL val[N] = {0};
void insert(LL id,string s){
	LL len = s.length(),now = rt;
	for(LL i = 0;i < len;i ++){
		if(!ch[s[i] - 'a'][now]) ch[s[i] - 'a'][now] = ++ tot;
		now = ch[s[i] - 'a'][now];
	}
	val[now] = id;
}

queue <LL> q;
void build(){
	for(LL i = 0;i < 2;i ++){
		if(ch[i][rt]){ fail[ch[i][rt]] = rt; q.push(ch[i][rt]); }
	}
	while(!q.empty()){
		LL u = q.front(); q.pop();
		for(LL i = 0;i < 2;i ++){
			if(ch[i][u]) fail[ch[i][u]] = ch[i][fail[u]],q.push(ch[i][u]);
			else ch[i][u] = ch[i][fail[u]];
		}
	}
}

LL f[NN][NN];
void query(LL id,string s){
	LL len = s.length(),now = rt;
	for(LL i = 0;i < len;i ++){
		now = ch[s[i] - 'a'][now];
		if(i != len - 1 && val[now]) f[val[now]][id] = 1;
		if(val[fail[now]]) f[val[fail[now]]][id] = 1;
	}
}
// AC Automaton

LL ec = 0,to[M],nxt[M],hed[NN << 1];
void add_edge(LL f,LL t){
	++ ec; to[ec] = t; nxt[ec] = hed[f]; hed[f] = ec;
}

LL vis[NN],p[NN],n;
void dfs(LL u){
	vis[u] = 1;
	for(LL i = hed[u];i;i = nxt[i]){
		LL v = to[i];
		if((u > n && p[u] == v) || (u <= n && p[u] != v)){
			if(!vis[v]) dfs(v);
		}
	}
}

LL dfs_mt(LL u){
	if(!u) return 1;
	for(LL i = hed[u];i;i = nxt[i]){
		LL v = to[i];
		if(vis[v]) continue;
		vis[v] = 1;
		if(dfs_mt(p[v])){
			p[u] = v; p[v] = u;
			return 1;
		}
	}
	return 0;
}

LL chs[NN];
LL solve(){
	LL ret = 0;
	for(LL i = 1;i <= n;i ++){
		for(LL j = 1;j <= n;j ++){
			if(f[i][j]) add_edge(i,j + n),add_edge(j + n,i);
		}
	}
	for(LL i = 1;i <= n;i ++){
		for(LL j = 1;j <= n + n;j ++) vis[j] = 0;
		if(dfs_mt(i)) ret ++;
	}
	for(LL j = 1;j <= n + n;j ++) vis[j] = 0;
	for(LL i = 1;i <= n;i ++) if(!p[i]) dfs(i);
	for(LL i = 1;i <= n;i ++) if(vis[i] && !vis[i + n]) chs[i] = 1;
	ret = 0; for(LL i = 1;i <= n;i ++) ret += chs[i];
	return ret;
}

string s[NN]; LL ans;
int main(){
	cin >> n;
	for(LL i = 1;i <= n;i ++){
		cin >> s[i];
		insert(i,s[i]);
	} build();
	for(LL i = 1;i <= n;i ++) query(i,s[i]);

	for(LL k = 1;k <= n;k ++){
		for(LL i = 1;i <= n;i ++){
			for(LL j = 1;j <= n;j ++){
				f[i][j] |= (f[i][k] & f[k][j]);
			}
		}
	} ans = solve();
	cout << ans << '\n';
	for(LL i = 1;i <= n;i ++) if(chs[i]) cout << i << ' '; cout << '\n';
	return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
using namespace std;
typedef int LL;
const LL N = 10000005,NN = 755,M = 600005;

LL ch[2][N],fail[N],rt = 0,tot = 0;
LL val[N] = {0},fa[N],ed[NN];
void insert(LL id,string s){
	LL len = s.length(),now = rt;
	for(LL i = 0;i < len;i ++){
		if(!ch[s[i] - 'a'][now]){
			ch[s[i] - 'a'][now] = ++ tot;
			fa[tot] = now;
		}
		now = ch[s[i] - 'a'][now];
	}
	val[now] = id; ed[id] = now;
}

queue <LL> q;
void build(){
	for(LL i = 0;i < 2;i ++){
		if(ch[i][rt]){ fail[ch[i][rt]] = rt; q.push(ch[i][rt]); }
	}
	while(!q.empty()){
		LL u = q.front(); q.pop();
		for(LL i = 0;i < 2;i ++){
			if(ch[i][u]) fail[ch[i][u]] = ch[i][fail[u]],q.push(ch[i][u]);
			else ch[i][u] = ch[i][fail[u]];
		}
	}
}

LL f[NN][NN];
vector <LL> v;
void query(LL id,string s){
	for(LL u = ed[id];u;u = fa[u]){
		LL fl = fail[u];
		while(!val[fl] && fl){
			v.push_back(fl);
			fl = fail[fl];
		}
		while(1){
			if(v.size() == 0) break;
			fail[v[v.size() - 1]] = fl;
			v.pop_back();
		}
//		if(fl) cout << val[fl] << "->" << id << endl;
		if(u != ed[id] && val[u]) f[val[u]][id] = 1;
//		if(u != ed[id] && val[u]) cout << val[u] << "->" << id << endl;
		if(fl) f[val[fl]][id] = 1;
	}
}
// AC Automaton

LL ec = 0,to[M],nxt[M],hed[NN << 1];
void add_edge(LL f,LL t){
	++ ec; to[ec] = t; nxt[ec] = hed[f]; hed[f] = ec;
}

LL vis[NN],p[NN],n;
void dfs(LL u){
	vis[u] = 1;
	for(LL i = hed[u];i;i = nxt[i]){
		LL v = to[i];
		if((u > n && p[u] == v) || (u <= n && p[u] != v)){
			if(!vis[v]) dfs(v);
		}
	}
}

LL dfs_mt(LL u){
	if(!u) return 1;
	for(LL i = hed[u];i;i = nxt[i]){
		LL v = to[i];
		if(vis[v]) continue;
		vis[v] = 1;
		if(dfs_mt(p[v])){
			p[u] = v; p[v] = u;
			return 1;
		}
	}
	return 0;
}

LL chs[NN];
LL solve(){
	LL ret = 0;
	for(LL i = 1;i <= n;i ++){
		for(LL j = 1;j <= n;j ++){
			if(f[i][j]) add_edge(i,j + n),add_edge(j + n,i);
		}
	}
	for(LL i = 1;i <= n;i ++){
		for(LL j = 1;j <= n + n;j ++) vis[j] = 0;
		if(dfs_mt(i)) ret ++;
	}
	for(LL j = 1;j <= n + n;j ++) vis[j] = 0;
	for(LL i = 1;i <= n;i ++) if(!p[i]) dfs(i);
	for(LL i = 1;i <= n;i ++) if(vis[i] && !vis[i + n]) chs[i] = 1;
	return ret;
}

string s[NN]; LL ans;
int main(){
	cin >> n;
	for(LL i = 1;i <= n;i ++){
		cin >> s[i];
		insert(i,s[i]);
	} build();
	for(LL i = 1;i <= n;i ++) query(i,s[i]);

	for(LL k = 1;k <= n;k ++){
		for(LL i = 1;i <= n;i ++){
			for(LL j = 1;j <= n;j ++){
				f[i][j] |= (f[i][k] & f[k][j]);
			}
		}
	}
	ans = n - solve();
	cout << ans << '\n';
	for(LL i = 1;i <= n;i ++) if(chs[i]) cout << i << ' '; cout << '\n';
	return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef int LL;
const LL N = 10000005,NN = 755,M = 5005;

LL ch[2][N],fail[N],rt = 0,tot = 0;
LL val[N] = {0};
void insert(LL id,string s){
	LL len = s.length(),now = rt;
	for(LL i = 0;i < len;i ++){
		if(!ch[s[i] - 'a'][now]) ch[s[i] - 'a'][now] = ++ tot;
		now = ch[s[i] - 'a'][now];
	}
	val[now] = id;
}

queue <LL> q;
void build(){
	for(LL i = 0;i < 2;i ++){
		if(ch[i][rt]){ fail[ch[i][rt]] = rt; q.push(ch[i][rt]); }
	}
	while(!q.empty()){
		LL u = q.front(); q.pop();
		for(LL i = 0;i < 2;i ++){
			if(ch[i][u]) fail[ch[i][u]] = ch[i][fail[u]],q.push(ch[i][u]);
			else ch[i][u] = ch[i][fail[u]];
		}
	}
}

LL f[NN][NN];
void query(LL id,string s){
	LL len = s.length(),now = rt;
	for(LL i = 0;i < len;i ++){
		now = ch[s[i] - 'a'][now];
		if(i != len - 1 && val[now]) f[val[now]][id] = 1;
		if(val[fail[now]]) f[val[fail[now]]][id] = 1;
	}
}
// AC Automaton

LL ec = 0,to[M],nxt[M],hed[NN << 1];
void add_edge(LL f,LL t){
	++ ec; to[ec] = t; nxt[ec] = hed[f]; hed[f] = ec;
}

LL vis[NN],p[NN],n;
void dfs(LL u){
	vis[u] = 1;
	for(LL i = hed[u];i;i = nxt[i]){
		LL v = to[i];
		if((u > n && p[u] == v) || (u <= n && p[u] != v)){
			if(!vis[v]) dfs(v);
		}
	}
}

LL dfs_mt(LL u){
	if(!u) return 1;
	for(LL i = hed[u];i;i = nxt[i]){
		LL v = to[i];
		if(vis[v]) continue;
		vis[v] = 1;
		if(dfs_mt(p[v])){
			p[u] = v; p[v] = u;
			return 1;
		}
	}
	return 0;
}

LL chs[NN];
LL solve(){
	LL ret = 0;
	for(LL i = 1;i <= n;i ++){
		for(LL j = 1;j <= n;j ++){
			if(f[i][j]) add_edge(i,j + n),add_edge(j + n,i);
		}
	}
	for(LL i = 1;i <= n;i ++){
		for(LL j = 1;j <= n + n;j ++) vis[j] = 0;
		if(dfs_mt(i)) ret ++;
	}
	for(LL j = 1;j <= n + n;j ++) vis[j] = 0;
	for(LL i = 1;i <= n;i ++) if(!p[i]) dfs(i);
	for(LL i = 1;i <= n;i ++) if(vis[i] && !vis[i + n]) chs[i] = 1;
	ret = 0; for(LL i = 1;i <= n;i ++) ret += chs[i];
	return ret;
}

string s[NN]; LL ans;
int main(){
	cin >> n;
	for(LL i = 1;i <= n;i ++){
		cin >> s[i];
		insert(i,s[i]);
	} build();
	for(LL i = 1;i <= n;i ++) query(i,s[i]);

	for(LL k = 1;k <= n;k ++){
		for(LL i = 1;i <= n;i ++){
			for(LL j = 1;j <= n;j ++){
				f[i][j] |= (f[i][k] & f[k][j]);
			}
		}
	} ans = n - solve();
	cout << ans << '\n';
	for(LL i = 1;i <= n;i ++) if(chs[i]) cout << i << ' '; cout << '\n';
	return 0;
}