2012-03-27 3 views
2

Мне нужно написать алгоритм, который читает поток клавиатуры, пока не получит правильный пароль.чтение пароля

, как если бы пароль был ababac, , а вход - abababa, это означает, что пока он читает ababa, и теперь он ждет, когда c будет разблокирован, если f вместо c, то он перезапустит свой процесс.

это легко сделать в O (n^2), но мой учитель хочет, чтобы мы сделали это в O (n) W.C, можно ли это сделать в этой сложности ?!

+0

ли вы имеете в виду, что читает первые октеты, если они «ababa», а затем просто бросают каждый октет, пока он не станет «c»? Как это сложно? просто в основном 'read', а затем опускайте октеты и сохраняйте трассировку, на которой вы находитесь в строке пароля ... нет? – Eregrith

+0

Нет, я отредактировал вопрос, чтобы очистить. –

ответ

1

Для этого вы можете построить automaton.

Для этого подхода вы можете использовать Aho–Corasick - создать автомат данных для строки и начать подавать его с текстом ввода до тех пор, пока вы не достигнете его конца [не принимаете], или вы достигли принимающего состояния в автомате ,

Ахо-Corasick линейна в шаблоне [пароль] и размера входных данных, так что вы получите O(m+n)

+0

Это не так тривиально, как вы выразились? ... обобщенный алгоритм для автоматизации всех возможных pw - это больше, чем мой учитель может потребовать ... –

+0

@OfekRon: (1) вопрос: «Можно ли это сделать в эта сложность?! - может быть, с Ахо-Корасиком (2) я согласен, что это не так просто, я сомневаюсь, что для него существует тривиальное линейное решение [если было, я не думаю, что было так много алгоритмов для подстроки паросочетания]. (3) Если ваш учитель ожидает «простого» - возможно, он/она ошибался в отношении сложности? – amit

+0

это может быть так, я очень сомневаюсь, что существует такое простое решение ... –

-5
password = "ababac" 
index = 0 
while index < password.length 
{ 
    read character into x 
    if(x == password[index]) 
    index++; 
} 

cout << "congrads!!! you got the password!!"; 
+1

Целью OP является обнаружение ключевых слов в потоке символов. Вы просто объединяете 'strcmp()' и I/O. – Philip

+0

Тип "zazzbzzzabzzazzc". – Chowlett

+0

вход ababafffc, который будет работать в вашем алгоритме –

0

Наивный подход будет хранить вход в круговом char буфер и использовать пользовательские strcmp(), чтобы проверить, содержит ли пароль. Этот метод находится в O (n).

+0

Да, этот метод O (n), но u активирует его O (n) раз, что приводит вас к O (n^2) ... –

+0

Ах, я получаю вашу мысль. Вы слышали о FSM? – Philip

+0

свяжите меня с этим и плохо читали об этом ... –

5

Я думаю, что онлайн-версия Knuth-Morris-Pratt algorithm выполнит эту работу. Однако вам придется хранить и вычислять индексный массив (дополнительная O (n) память в случае реализации циклического массива).

+0

Я сомневаюсь, что это приведет вас к O (n) в онлайн-версии ... попробуйте псевдокод и посмотрите ... –

+0

Онлайн-алгоритм берет O (PASSWORD_SIZE) для предварительной обработки и O (INPUT_SIZE) для остальной части алгоритма. –

0

это ближайший я получил Linear время ...

#include<stdio.h> 
#include<stdlib.h> 
#include<dos.h> 
#include<string.h> 

typedef struct node_t { 
    char c; 
    struct node_t * next; 
    struct node_t * prev; 
} node; 


void pop(); 
void printIT(node *p); 
void fixList(); 
char addToList(char c); 
long silence_keyboard(char pw[] ,int size); 

char pw[256]; 
node *head = NULL; 
node *tail = NULL; 
int i = 0 , listSize = 0; 



void main(void) 
{ 
    printf("Set PW:"); 
    scanf("%s",pw); 
    printf("Enter PW (silence_keyboard is activated):\n"); 
    printf("\npw was entered.",silence_keyboard(pw,strlen(pw))); 
} 


long silence_keyboard(char pw[] ,int size) { 
    while (i<size) { 
     for (; i<size && addToList(getche())==pw[i] ; i++); 
     if (i<size) fixList(); 
    } 
    return 0; 
} 

char addToList(char c) { 
    node *temp=(node *)malloc(sizeof(node)); 
    if (!temp) exit(1); 
    temp->c=c; 
    temp->next=NULL; 
    temp->prev=tail; 
    if (!tail) head=temp; 
    else tail->next=temp; 
    tail=temp; 
    listSize++; 
    return c; 
} 

void fixList() { 
    node *p=tail; 
    int j; 
    while (1) { 
     for (; i>=0 && pw[i]!=tail->c ; i--) { 
      pop(); 
      printf("\nso far:"); 
      printIT(head); 
      printf(" pw:%s\n",pw); 
     } 
     for (p=tail,j=i ; j>=0 && pw[j]==p->c ; j-- , p=p->prev); 
     if (j<0) break; 
     else { 
      pop(); 
      printf("\nso far:"); 
      printIT(head); 
      printf(" pw:%s\n",pw); 
      i--; 
     } 
    } 
    i=listSize; 
} 

void printIT(node *p) { 
    if (p) { 
     printf("%c",p->c); 
     printIT(p->next); 
    } 
    else { 
     printf("\n"); 
     return; 
    } 

} 

void pop() { 
    node *p=head; 
    if (!head) return; 
    if (head==tail) tail=NULL; 
    head=head->next; 
    free(p); 
    listSize--; 
}