// c.durr - 2015 - upmc
// streaming algorithms
// Misra-Gries

import java.util.*;
import java.io.*;

class FluxIP {
	Scanner in;

	FluxIP(String filename) throws FileNotFoundException {
		in = new Scanner(new File(filename));
	}

	public boolean hasNext() {
		return in.hasNext();
	}

	public long next() {
        int   d = 0; // nombre décimal
        long ip = 0; // adresse ip
        String line = in.nextLine();
        for (int i=0; i<line.length(); i++) {
         	char c = line.charAt(i);
            if (Character.isDigit(c))
                d = 10 * d + c - '0';
            else if (c=='.') {
                ip += d;
                d = 0;
                ip *= 256; // décalage
            }
            else
                break;
        }
		return ip + d;
	}

	static String ipname(long ip) {
		return ((ip>>24)&255) + "." + ((ip>>16)&255) + "." + ((ip>>8)&255) + "." + (ip&255);
	}
}

class MisraGries {
	int k;
	int n;
	double delta;
    HashMap<Integer,Integer> A;
    int round;

	MisraGries(double delta) {
		this.k = (int)(1/delta + 1);  // arrondir vers le haut
		this.delta = delta;
        A = new HashMap<Integer,Integer>();
        round = 1;
	}

	void changeRound() {
		assert(round==1);
		round = 2;
		n = 0;
    	for (int key: A.keySet())     // remettre compteurs à zéro
    		A.put(key, 0);
	}

	void update(int ip) {
		if (round==1)
		    if (A.containsKey(ip))
		        A.put(ip, A.get(ip)+1);
		    else if (A.size()<k)
		    	A.put(ip, 1);
		    else {                    // décrémenter les compteurs
				Iterator<Map.Entry<Integer,Integer>>  it = A.entrySet().iterator();
				while (it.hasNext()) {
					Map.Entry<Integer,Integer> keyval = it.next();
					if (keyval.getValue()==1)
						it.remove();  // enlever ceux qui deviennent zéro
					else
						A.put(keyval.getKey(), keyval.getValue() - 1);
				}
	    	}
    	else {                        // round 2: déterminer les fréquences exacts
    		n++;
    		if (A.containsKey(ip))
    			A.put(ip, A.get(ip) + 1);
    	}
	}

	HashMap<Integer,Integer> val() {
		Iterator<Map.Entry<Integer,Integer>>  it = A.entrySet().iterator();
		while (it.hasNext()) {
			int key = it.next().getKey();
			if (A.get(key) < n*delta)
				it.remove();          // enlever éléments dont la fréquence n'est pas assez
		}
		return A;
	}

	public static void main(String args[]) throws FileNotFoundException {
		if (args.length!=2) {
			System.err.println("Usage: java MisraGries <filename> <delta>\n" +
							   "   returns elements with frequency at least delta");
			System.exit(1);
		}
		String filename = args[0];
		double delta = Double.parseDouble(args[1]);
		MisraGries a = new MisraGries(delta);
		FluxIP  f = new FluxIP(filename);       // premier passage pour estimer les fréquences
		while (f.hasNext())
			a.update((int)f.next());
		a.changeRound();
		f = new FluxIP(filename);               // deuxième passage pour les fréquences exacts de ces clés
		while (f.hasNext())
			a.update((int)f.next());
		HashMap<Integer,Integer> A = a.val();
		for (int ip: A.keySet())                // afficher la solution
			System.out.println(A.get(ip) + "\t" + FluxIP.ipname(ip));
	}
}
