from heapq import heappush, heappushpop
with open("test.in", "r") as f:
l = f.read().splitlines() # читаем файл а список строк
n, d = int(l[0]), {} # n из условия, d - словарь (хэштаблица)
hpp = (heappush, heappushpop)
for i in range(1, n + 1): # перебираю инициализирующие строки
w, s = l[i].split() # расщепляю
t = (int(s), w) # создаю кортеж вида (целое, слово)
while w: # пока в слове есть буквы
w = w[:-1] # отрезаю его последнюю букву - так я перебираю префиксы
if w in d: # если префикс уже в словаре
ww = d[w] # ww - это буфер из не более чем 10 кортежей, ...
hpp[len(ww) > 9](ww, t) # добавляю либо вытесняю кортеж с минимальным числом
else:
d[w] = [t] # создаю и добавляю в словарь новый буфер
for w in l[n + 2:]: # перебираю запросы
print(" ~ %s" % w) # вот префикс
if w in d: # если префикс в словаре
for t in sorted(d[w], reverse=True):
print("%6d %s" % t) # печатаю отсортированный буфер
for t in sorted(d[w], reverse=True):
print("%6d %s" % t)
)from heapq import heappush, heappushpop
with open("test.in", "r") as f:
l = f.read().splitlines()
n, root = int(l[0]), ([], [None] * 26) # root - кортеж из пустого буфера и
# списка nil-ссылок на дочерние узлы
hpp = (heappush, heappushpop)
for i in range(1, n + 1):
w, s = l[i].split()
t = (int(s), w)
node = root
for c in w:
child = node[1][ord(c) - 97] # ord('a') == 97
if child is None:
node[1][ord(c) - 97] = child = ([t], [None] * 26)
else:
ww = child[0]
hpp[len(ww) > 9](ww, t)
node = child
for w in l[n + 2:]:
print(" ~ %s" % w)
node = root
for c in w:
child = node[1][ord(c) - 97]
if child is None:
break
node = child
else:
for t in sorted(child[0], reverse=True):
print("%6d %s" % t)
package test;
import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
/**
* Created by nemo_odissey on 10.07.2017 12:45 for <a href="https://toster.ru/q/440261?utm_source=email_notifications&utm_medium=email&utm_content=mention&utm_campaign=notifications#comment_1428657" >Какую сортировку применять?</a>.
*/
public class JapanEditor
{
/**
* Compare by frequence and if equal, compare lexicographically
*/
public static class ComparePrefixWithFreq implements Comparator
{
@Override
public int compare( Object obj1, Object obj2 )
{
int cmp = ((WordItem) obj2).count - ((WordItem) obj1).count; // compare in reverse frequencies
if ( cmp != 0 ) // texts are not equals
return cmp;
return((WordItem)obj1).word.compareTo( ((WordItem)obj2).word ); // if freqs are equal, compare lexicographically
}
}
/**
* Class to store vocabulary item and make it comparable only lexicographically
*/
public static class WordItem implements Comparable
{
public String word;
public int count;
public WordItem( String word, int count )
{
this.count = count;
this.word = word;
}
@Override
public int compareTo( Object obj )
{
return this.word.compareTo( ((WordItem)obj).word );
}
}
/**
* Обработки ошибок НЕТ
* @param args путь_к_файлу_с_данными, где хранится задание
* @throws IOException
*/
public static void main( String[] args ) throws IOException
{
long start = new Date().getTime();
BufferedReader brd = new BufferedReader( new FileReader(args[0]), 32 * 1024 );
// читаем число слов
int wordCnt = Integer.parseInt( brd.readLine() );
WordItem[] wordArr = new WordItem[wordCnt];
// Читаем все слова и их частоты
for(int i = 0; i < wordCnt; i++)
{
String[] elems = brd.readLine().split( " " );
wordArr[ i ] = new WordItem( elems[0], Integer.parseInt( elems[1] ) );
}
// сортируем массив словаря
Arrays.sort( wordArr );
// сортировщик по частоте
ComparePrefixWithFreq compareWithFrequence = new ComparePrefixWithFreq();
// считываем и обрабатываем каждый префикс один за другим
int prefCnt = Integer.parseInt( brd.readLine() );
System.out.printf( "Счётчик слов %d, счётчик префиксов %d\n", wordCnt, prefCnt );
System.out.printf( "Словарь считан и отсортирован за %,d млс.\n\n", new Date().getTime() - start );
int summaryWordCount = 0;
WordItem prefixItem = new WordItem( null, 1 );
for(int i = 0; i < prefCnt; i++)
{
String prefix = brd.readLine().trim();
prefixItem.word = prefix;
int pos = Arrays.binarySearch(wordArr, prefixItem ); // if positive, point to a word in vocabulary started from prefix or equal to it
if ( pos < 0) // no precise prefix value found in vocabulary
pos = -(pos + 1); // pos to the first element starting from prefix
if ( pos >= wordCnt) // префикс отсутствует в словаре
continue;
if ( wordArr[pos].word.startsWith( prefix )) // Если префикс есть, ищем его конец в словаре
{
char nextLastChar = prefix.charAt( prefix.length() - 1 );
prefixItem.word = prefix.substring( 0, prefix.length() -1 ) + (++nextLastChar); // готовим следующую не строку
int pos1 = Arrays.binarySearch( wordArr, pos, wordCnt, prefixItem ); // ищем последнее вхождение префикса в словаре
if ( pos1 < 0)
pos1 = -pos1;
if ( pos1 > wordCnt)
pos1 = wordCnt;
summaryWordCount += pos1 - pos;
// pos -> first word with prefix, pos1 -> first word without prefix
WordItem[] wordsWithPrefix = Arrays.copyOfRange( wordArr, pos, pos1 );
Arrays.sort( wordsWithPrefix, compareWithFrequence );
int wordWithPrefCnt = Math.min( wordsWithPrefix.length, 10 );
for( int j = 0; j < wordWithPrefCnt; j++ )
//System.out.printf("%s %d\n", item.word, item.count); // debug output
System.out.println( wordsWithPrefix[j].word );
System.out.println(""); // add empty line according to the task requirements
}
}
brd.close();
System.out.printf( ">>> Длительность обработки %,d млс., средний размер выборки по каждому префиксу %d\n", new Date().getTime() - start, summaryWordCount / prefCnt);
}
}
int pos = Arrays.binarySearch(wordArr, prefixItem ); // if positive, point to a word in vocabulary started from prefix or equal to it
if ( pos < 0) // no precise prefix value found in vocabulary
{
pos = -(pos + 1); // pos to the first element starting from prefix
}
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
/**
* Created by nemo_odissey on 10.07.2017 12:45 for
* <a href="https://toster.ru/q/440261?utm_source=email_notifications&utm_medium=email&utm_content=mention&utm_campaign=notifications#comment_1428657" >Какую сортировку применять?</a>.
*/
public class JapanEditor
{
/**
* Class to store vocabulary item and make it comparable only lexicographically
*/
public static class WordItem implements Comparable
{
public String word;
public int count;
public WordItem( String word, int count )
{
this.count = count;
this.word = word.split( "/",0 )[0];
}
@Override
public int compareTo( Object obj )
{
return this.word.compareTo( ((WordItem)obj).word );
}
public int compareByFrequency( Object obj )
{
return this.count - ((WordItem)obj).count;
}
}
/**
* Сортирует и извлекает из массива source начиная с индекса pos1 и до индекса pos2 (не включая его самого) максимальные элементы,
* по размеру массива result или меньше.
* @param maxLen максимальный размер массива с максимальными элементами
* @param dstList {@link ArrayList} для размещения результатов работы. Если {@code null}, то будет создан внутри. Очищается перед работой и заполняется результатами
* @param source исходный массив
* @param pos1 начальный индекс массива source
* @param pos2 конечный инидекс в массиве source (не включается в сортировку)
* @return {@link ArrayList} (не может быть {@code null})
*/
public static final ArrayList<WordItem> partialSort( int maxLen, ArrayList<WordItem> dstList, WordItem[] source, int pos1, int pos2 )
{
if ( dstList == null )
dstList = new ArrayList<WordItem>( 10 );
else
dstList.clear();
dstList.add( source[ pos1++ ] );
// Проверим все слова с префиксом на предмет их частоты и отберём до 10 самых часто встречающихся
for( int i = pos1; i< pos2; i++ )
{
WordItem item = source[ i ];
int placeFound = 0;
int listPos;
int cmp;
// Найдём, надо ли вставлять и куда вставить
for ( listPos = dstList.size() - 1; listPos >= 0; listPos-- )
{
if ( ( cmp = item.compareByFrequency( dstList.get( listPos ) ) ) < 0 ) // нашли элемент из списка проверенных, который больше проверяемого
break; // дальше не идём, может сможем добавить в конец списка, если там ещё есть место
if (cmp == 0) // по частоте он равен
if ( item.compareTo( dstList.get( listPos ) ) > 0 ) // но элемент из списка проверенных оказался меньше лексически
break;
}
// пытаемся вставить в массив либо на место элемента, который меньше, либо в конец списка, если там ещё есть место
if ( listPos == (dstList.size()-1) ) // младший элемент списка больше проверяемого элемента, попробуем просто сдобавить в конец
{
if ( dstList.size() < maxLen ) // массив результата ещё не полон, добавляем в конец
dstList.add( item );
continue; // переходим к следующему элементу
}
// нашли, куда вставить
if ( dstList.size() == maxLen )
{
// массив результата уже полностью заполнен, сразу удаляем нижний,
// т.к. он выйдет за разрешённые пределы при вставке нового элемента
dstList.remove( maxLen - 1 );
}
// вставляем ниже большего элемента, или, если listPos == -1, вместо самого большого
dstList.add( listPos + 1, item );
}
return dstList;
}
/**
* Обработки ошибок НЕТ
* @param args путь_к_файлу_с_данными, где хранится задание
* @throws IOException
*/
public static void main( String[] args ) throws IOException
{
long start = System.nanoTime();
BufferedReader brd = java.nio.file.Files.newBufferedReader( Paths.get( args[ 0 ] ), Charset.forName( "utf-8" ) );
// читаем число слов
int wordCnt = Integer.parseInt( brd.readLine() );
WordItem[] wordArr = new WordItem[wordCnt];
// Читаем все слова и их частоты
for(int i = 0; i < wordCnt; i++)
{
String word = brd.readLine();
String[] elems = word.split( " " );
wordArr[ i ] = new WordItem( elems[0], Integer.parseInt( elems[1] ) );
// wordArr[ i ] = new WordItem( word.toLowerCase(), freq );
}
// сортируем массив словаря
Arrays.sort( wordArr );
// считываем и обрабатываем каждый префикс один за другим
int prefCnt = Integer.parseInt( brd.readLine() );
System.out.printf( "Счётчик слов %d, счётчик префиксов %d\n", wordCnt, prefCnt );
System.out.printf( "Словарь считан и отсортирован за %,f млс.\n\n", 1e-9 * (System.nanoTime() - start) );
int summaryWordCount = 0;
WordItem prefixItem = new WordItem( "", 1 );
ArrayList<WordItem> list = new ArrayList<>( 11 );
for(int i = 0; i < prefCnt; i++)
{
String prefix = brd.readLine().trim();
prefixItem.word = prefix;
int pos1 = Arrays.binarySearch( wordArr, prefixItem ); // if positive, point to a word in vocabulary started from prefix or equal to it
if ( pos1 < 0) // no precise prefix value found in vocabulary
pos1 = -(pos1 + 1); // pos1 to the first element starting from prefix
if ( pos1 >= wordCnt) // префикс отсутствует в словаре
continue;
System.out.printf( " ~ %s\n", prefix );
if ( wordArr[pos1].word.startsWith( prefix ) ) // Если префикс есть, ищем последнюю его позицию в словаре
{
char nextLastChar = prefix.charAt( prefix.length() - 1 );
prefixItem.word = prefix.substring( 0, prefix.length() -1 ) + (++nextLastChar); // готовим следующую не строку
int pos2 = Arrays.binarySearch( wordArr, pos1, wordCnt, prefixItem ); // ищем последнее вхождение префикса в словаре
if ( pos2 < 0)
pos2 = -pos2 -1;
if ( pos2 > wordCnt)
pos2 = wordCnt;
summaryWordCount += pos2 - pos1;
list = partialSort( 10, list, wordArr, pos1, pos2 );
for( WordItem item: list )
System.out.printf( "%6d %s\n", item.count, item.word );
}
}
brd.close();
System.out.printf( ">>> Длительность обработки %,f сек., средний размер выборки по каждому префиксу %d\n", 1e-9 * (System.nanoTime() - start), summaryWordCount / prefCnt);
}
}