Problem: Today is birthday of a Little Dasha — she is now 8 years old! On this occasion, each of her n friends and relatives gave her a ribbon with a greeting written on it, and, as it turned out, all the greetings are different. Dasha gathered all the ribbons and decided to throw away some of them in order to make the remaining set stylish. The birthday girl considers a set of ribbons stylish if no greeting written on some ribbon is a substring of another greeting written on some other ribbon. Let us recall that the substring of the string s is a continuous segment of s.

Help Dasha to keep as many ribbons as possible, so that she could brag about them to all of her friends. Dasha cannot rotate or flip ribbons, that is, each greeting can be read in a single way given in the input.

Input

The first line of the input contains integer n (1 ≤ n ≤ 750) — the number of Dasha's relatives and friends.

Each of the next n lines contains exactly one greeting. Each greeting consists of characters 'a' and 'b' only.

The total length of all greetings won't exceed 10 000 000 characters.

Output

In the first line print the maximum size of the stylish set. In the second line print the numbers of ribbons involved in it, assuming that they are numbered from 1 to n in the order they appear in the input. If there are several stylish sets of the maximum size, print any of them.

Examples

Input

5
abab
aba
aabab
ababb
bab


Output

2
2 5

Note

In the sample, the answer that keeps ribbons 3 and 4 is also considered correct.

Solution (in JAVA):

Solution:
//package round327;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Queue;

public class E4 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
	
	void solve()
	{
		int n = ni();
		char[][] ss = new char[n][];
		for(int i = 0;i < n;i++)ss[i] = ns().toCharArray();
		int numnode = 1;
		for(char[] s : ss)numnode += s.length;
		TrieArrayByArray trie = new TrieArrayByArray(numnode, 2);
		boolean[][] g = new boolean[n+1][n+1];
		boolean[] ignore = new boolean[n+1];
		for(int i = 0;i < n;i++){
			boolean res = trie.add(ss[i], i+1);
			if(!res){
				ignore[i+1] = true;
			}
		}
		trie.buildFailure(g);
		
		for(int i = 0;i < n;i++){
			if(ignore[i+1])continue;
			int cur = 0;
			for(char x : ss[i]){
				if(trie.hit[cur] > 0){
					g[i+1][trie.hit[cur]] = true;
				}
				cur = trie.next[trie.f(x)][cur];
			}
			assert trie.hit[cur] == i+1;
		}
		
		g = wfx(g);
//		for (int k = 0; k < n+1; k++) {
//			for (int i = 0; i < n+1; i++) {
//				for (int j = 0; j < n+1; j++) {
//					g[i][j] |= g[i][k] & g[k][j];
//				}
//			}
//		}
		int[] mat = doBipartiteMatching(g);
		boolean[] mincover = mincover(g, mat);
		List<Integer> ans = new ArrayList<>();
		for(int i = 1;i <= n;i++){
			if(!ignore[i] && !(mincover[i] || mincover[i+n+1])){
				ans.add(i);
			}
		}
		out.println(ans.size());
		for(int v : ans)out.print(v + " ");
		out.println();
	}
	
	boolean[][] wfx(boolean[][] g)
	{
		int n = g.length;
		int m = (n>>>6)+1;
		long[][] rg = new long[n][m];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				if(g[i][j]){
					rg[i][j>>>6] |= 1L<<j;
				}
			}
		}
		
		for (int k = 0; k < n; k++) {
			for (int i = 0; i < n; i++) {
				if(g[i][k]){
					for(int j = 0;j < m;j++){
						rg[i][j] |= rg[k][j];
					}
				}
			}
		}
		
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				g[i][j] = rg[i][j>>>6]<<~j<0;
			}
		}
		return g;
	}
	
	boolean[] mincover(boolean[][] g, int[] mat)
	{
		int n = g.length, m = g[0].length;
		boolean[] z = new boolean[n+m];
		Queue<Integer> q = new ArrayDeque<Integer>();
		for(int i = 0;i < n;i++){
			if(mat[i] == -1){
				z[i] = true;
				q.add(i);
			}
		}
		while(!q.isEmpty()){
			int cur = q.poll();
			if(cur < n){
				for(int i = 0;i < m;i++){
					if(g[cur][i] && mat[cur] != i && !z[i+n]){
						z[i+n] = true;
						q.add(i+n);
					}
				}
			}else{
				for(int i = 0;i < n;i++){
					if(mat[i] == cur-n && !z[i]){
						z[i] = true;
						q.add(i);
						break;
					}
				}
			}
		}
		
		// minimum vertex cover = (L and not Z) or (R and Z)
		for(int i = 0;i < n;i++)z[i] ^= true;
		return z;
	}
	
	public static int[] doBipartiteMatching(boolean[][] g)
	{
		int n = g.length;
		if(n == 0)return new int[0];
		int m = g[0].length;
		if(m == 0)return new int[n];
		int[] im = new int[m];
		Arrays.fill(im, -1);
		BitSet visited = new BitSet();
		int matched = 0;
		for(int i = 0;i < n;i++){
			if(visit(g, i, visited, im)) {
				visited.clear();
				matched++;
			}
		}

		int[] ret = new int[n];
		Arrays.fill(ret, -1);
		for(int i = 0;i < m;i++){
			if(im[i] != -1)ret[im[i]] = i;
		}
		return ret;
	}

	public static boolean visit(boolean[][] g, int cur, BitSet visited, int[] im)
	{
		if(cur == -1)return true;

		for(int i = visited.nextClearBit(0);i != g[cur].length;i = visited.nextClearBit(i+1)){
			if(g[cur][i]){
				visited.set(i);
				if(visit(g, im[i], visited, im)){
					im[i] = cur;
					return true;
				}
			}
		}
		return false;
	}

	
	public static int[] sortTopologically(boolean[][] g)
	{
		int n = g.length;
		int[] ec = new int[n];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				if(g[i][j])ec[j]++;
			}
		}
		int[] ret = new int[n];
		int p = 0;
		int q = 0;
		
		ost:
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				if(g[j][i])continue ost;
			}
			ret[q++] = i;
		}
		
		for(;p < q;p++){
			int cur = ret[p];
			for(int i = 0;i < n;i++){
				if(g[cur][i]){
					ec[i]--;
					if(ec[i] == 0)ret[q++] = i;
				}
			}
		}
		for(int i = 0;i < n;i++){
			if(ec[i] > 0){
				return null;
			}
		}
		return ret;
	}

	
	public static void tf(boolean[][] b) {
		for (boolean[] r : b) {
			char[] s = new char[r.length];
			for (int i = 0; i < r.length; i++)
				s[i] = r[i] ? '#' : '.';
			System.out.println(new String(s));
		}
		System.out.println();
	}
	
	public class TrieArrayByArray {
		// root = 0
		public int K;
		public int[][] next;
		public int gen;
		public int size;
		
		public int[] hit;
		
		public int[] fail;
		
		public TrieArrayByArray(int n, int K)
		{
			this.K = K;
			this.size = n;
			this.next = new int[K][n];
			this.hit = new int[n];
			this.gen = 1;
			
			for(int i = 0;i < K;i++)Arrays.fill(this.next[i], -1);
		}
		
		public int f(char c)
		{
			return c - 'a';
		}
		
		public boolean add(char[] s, int id)
		{
			int cur = 0;
			for(char c : s){
				int v = f(c);
				int nex = next[v][cur];
				if(nex == -1)nex = next[v][cur] = gen++;
				cur = nex;
			}
			if(hit[cur] >= 1)return false;
			hit[cur] = id;
			return true;
		}
		
		public void buildFailure(boolean[][] g)
		{
			this.fail = new int[this.size];
			Arrays.fill(this.fail, -1);
			int[] q = new int[gen];
			int p = 1;
			for(int r = 0;r < p;r++){
				int cur = q[r];
				inner:
				for(int i = 0;i < K;i++){
					int ch = next[i][cur];
					if(ch == -1)continue;
					q[p++] = ch;
					for(int to = fail[cur]; to != -1; to = fail[to]){
						int fch = next[i][to];
						if(fch == -1)continue;
						fail[ch] = fch;
						if(hit[fch] >= 1 && hit[ch] >= 1){
							g[hit[ch]][hit[fch]] = true;
						}else if(hit[ch] == 0){
							hit[ch] = hit[fch];
						}
						continue inner;
					}
					fail[ch] = 0; // failed to root
				}
			}
			assert p == gen;
		}
		
		public int next(int cur, char c)
		{
			for(;cur != -1;cur = fail[cur]){
				int ch = next[f(c)][cur];
				if(ch != -1)return ch;
			}
			return 0;
		}
		
	}
	
	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);
		
		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}
	
	public static void main(String[] args) throws Exception { new E4().run(); }
	
	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;
	
	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}
	
	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }
	
	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }
	
	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}
	
	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}
	
	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}
	
	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}
	
	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}
		
		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}
	
	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}
		
		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}
	
	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}