2013-11-11 5 views
1

Ques1
Задана строка, содержащая только символы '(', ')', '{', '}', '[' and ']', например, "[{()}]", вам нужно написать функцию, которая будет проверять достоверность такой входной строки.Действительность paranthesized строки параллельной обработки

Я могу сделать это с помощью стеков.

Ques2
Делают это с помощью нескольких процессоров одновременно.

Как это сделать?

По мне, это не может быть сделано, потому что:
Допустим, у нас есть 3 процессоров и входной строки: ([{([])}]) и разделить на 3 процессорах:
первый: ([{
второй: ([]
3rd: )}])
Теперь, применяя эту процедуру, мы получаем FALSE со всех трех процессоров, поэтому ее нельзя решить путем параллельной обработки.
Is it right or parallel processing means something else ?

ответ

3

Один из способов сделать это - это запустить первый поток в начале строки и использовать стек для обработки первой половины строки. Второй поток начинается в конце строки и обрабатывает вторую половину строки в обратном порядке.

Если оба потока завершили эту первую фазу, то первая нить рассматривает стек второго потока как продолжение строки.

Так, к примеру, у вас есть:

[({(())}[])] 

нить 1 получает [({((), и поток 2 получает )}[])]

каждый из них обработку тир отделки, в результате чего в этих двух стеков (левая вершина стека):

`({([` `)})]` 

Затем нить 1 может превратить поток 2 в стек в строку (или рассматривать стек в виде строки, выскакивает один символ за один раз), а также со ntinue его обработки.

Подумайте об этом, когда две нити обработаны своей половиной строки, два стека должны быть одинаковой длины, и они являются зеркалами друг друга. Стек первого потока будет содержать только открывающие разделители (например, '(', '[' или '{'), а стек второго потока будет содержать только закрывающие разделители. Таким образом, после того как оба потока завершатся с половиной обработки, заключительная часть просто:

while (stack1.Count > 0 && stack2.Count > 0) 
{ 
    left = stack1.Pop(); 
    right = stack2.Pop(); 
    if (!delimiters_match(left, right)) 
    { 
     // error! 
    } 
} 

Обратите внимание, что в любое время обработки, это возможно либо нить для обнаружения ошибки, например, при:.

([){})[) 

Первая нить знает, что ошибка произошел в третьем символе, потому что у вас не может быть ) сразу последовать за [. Аналогичным образом второй ead знает, что есть ошибка с [ (рядом с последним символом), потому что вы не можете иметь [ непосредственно перед ).

Но некоторые ошибки могут быть обнаружены только во время второй фазы. Например:

({[}]) 

Подлинности слева и справа действительны, но в сочетании они не являются.

2

Ну, пример, который вы выбрали, не может быть разрешен параллельно в том порядке, в котором вы его устанавливаете.

Рассмотрите вместо этого тестовое выражение, скажем, 200000 символов. Разделите это на 2 процессора (давайте все упростим). Каждый процессор:

  1. сканов его подстрока для любых вхождений [], {} или (), то есть из двух последовательных символов, которые образуют правильную строку. Когда он находит такое событие, он просто удаляет его.
  2. Повторите шаг 1, пока в подстроку не будет внесено никаких изменений.
  3. Рекомбинируйте подстроки и повторите шаг 1 процессора 1, пока ничего не изменится.

Я ожидаю, что кто-то с большим количеством времени, чем я имел сейчас, мог бы построить примеры, которые так длинны, что рекурсивное разделение на 2, 4, 8, ... процессоры или через 3, 6, 9, .. . Было бы полезно. Я ожидаю, что также можно построить примеры, которые не ускоряются, на самом деле наоборот, если они разделены между процессорами.

Смежные вопросы