7

この投稿で説明するように、非決定性有限オートマトンをシミュレートするための割り当てを行っています。この入力をファイルから読み取らせますtarea4.in

1
6 8 0 2
2
5
0 0 a
0 1 a
1 1 b
1 2 c
1 3 c
3 4 d
4 4 d
4 5 d
5
aaabcccc
aabbbbcdc
abbcdddcc
acdddddd
abc

入力の最初の行は整数Tで、プログラムを評価するケースの数を表します。各テストケースは4つの整数で始まり、最初はオートマトンの状態の数、次はオートマトンの遷移の数、3番目の数は初期状態、そして最後の状態の数です。次に、最終状態が発生します(この例では、最終状態は2と5です)。次に、Eが最終状態であることを表す整数Eを持つF行が来ます。

次に、N行(Nは遷移の数)が来ます。それぞれ2つの整数と、遷移、つまり遷移が状態iから状態Jに文字Cで進む状態を表す文字I、J、およびCがあります。この行の後には、テストする文字列の数を含む単一の整数Sが続き、次にそれぞれの文字列を含むS行が続きます。

期待される出力は次のとおりです。

Test Case #2:
aaabcccc Rejected
aabbbbcdc Rejected
abbcdddcc Rejected
acdddddd Accepted
abc Accepted

私のコードに帰着する出力:

Test Case #1:
aaabcccc Rejected
aabbbbcdc Rejected
abbcdddcc Rejected
acdddddd Rejected
abc Rejected

これが私のコードです:

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <vector>    
using namespace std;

typedef map<pair<int, int>, char> transitions;
    transitions trans;

    int  numberFinals;
    vector<int> currentStates;    

int main (){ 

    freopen ("tarea4.in", "r", stdin);
    //freopen ("tarea4.out", "w", stdout);        
    int testCases, i, j,k, cont=1,finalStates,numberInputs,stateOrigin, stateDestination;
    int numberStates, numberTransitions, initialState;
    char transitionCharacter ;

    set<int> current;
    set<int> next;
    set<int>::iterator it;
    set <int> final;
    std::set<int> the_intersection;  // Destination of intersect
    map<pair<int, int>, char>::iterator p;
    string inputString;

    cin>> testCases;
    for (i=0;i< testCases;i++){
        cin>>numberStates>>numberTransitions>>initialState>>numberFinals;
        current.insert (initialState);

        for (j=0;j<numberFinals;j++){
            cin>>finalStates;
            final.insert(finalStates);
        }

        for (j=0; j<numberTransitions;j++){
            cin>> stateOrigin>>stateDestination>>transitionCharacter;
            trans.insert(transitions::value_type(std::make_pair(stateOrigin, stateDestination), transitionCharacter ));
       }

        cin>>numberInputs;

        cout<<"Test Case #"<<cont++<<":"<<endl;    

        for (j=0; j<numberInputs;j++){
             //////////////////the code of the answer /////////////////
            current.insert (initialState);
            cin>> inputString;
            cout<<inputString<<" ";


     for (k=0; k<str.size();k++){
         next.clear();
         for ( it=current.begin() ; it != current.end(); it++ ){
              for (q= trans.begin(); q!= trans.end();q++){
                  if((*it == q->first.first)&&(str[k]==q->second)){
                     next.insert(q->first.second);
                   }
              current=next;
              }
         }
     }

            std::set_intersection(current.begin(), current.end(), final.begin(), final.end(), std::inserter(the_intersection, the_intersection.end()));

            if (the_intersection.size()>0){
                cout<< "Accepted"<<endl;
            }
            else{
                cout<< "Rejected"<<endl;
            }

        }

        printf ("\n");
    }

return 0;
}

私の質問は:なぜ私は間違った出力を得るのですか?テストケースで定義されたオートマトンの非決定性のためだと思いますが、文字列を正しく評価するにはどうすればよいですか?呼び出された関数evaluate_stringを何らかの方法で変更して、非決定論によって文字列を評価するためにオートマトンを使用できるさまざまなパスを確認するにはどうすればよいですか?

私はこれに数日間立ち往生していて、正直に言うと私はやや必死です。

4

3 に答える 3

10

NFAの評価は、DFAの評価とほぼ同じくらい簡単です。

DFAには、現在の状態が1つあり、各ステップで次の遷移を選択します。入力の最後に、現在の状態が受け入れ状態であるかどうかを確認します。

NFAには一連の現在の状態があり、各ステップですべての現在の状態を調べ、それぞれについて、すべての有効な遷移を選択します。これらの組み合わされたセットは、新しい状態セットを形成します。

最後に、現在の状態と受け入れ状態の共通部分が空でないかどうかを確認します。

擬似コードでは、これは次のようになります。

  • 現在={初期}
  • 入力の各文字 に対して
    • next = {}
    • 現在の状態 ごと
      • 遷移[状態][ char ]∪遷移[状態][ ϵ ]の各遷移 に対して
        • 次へ追加target_of遷移))
    • 現在=
  • if lenintersectioncurrentaccepting))> 0:
    • 印刷 "String accepted"
  • その他
    • 印刷 "String rejected"

これは、 1ずつC++コードに変換できます。これを簡単にするstd::set<int>ために、currentnextセット、およびstd::multimap<char, int>遷移のベクトルを使用することをお勧めします。これは、各状態が整数に対応することを前提としています。

于 2012-05-17T10:13:37.960 に答える
1

まず、NFAを対応するDFAに変換するための一般的なメカニズムを実装する必要があると思います。その後、DFAは決定論的に機能するため、オートマトンランナーを簡単に実装できます。

于 2012-05-16T21:16:37.013 に答える
1

基本的な問題は、最初の有効な遷移が見つかるとすぐに、コードが遷移ループから抜け出すことです。これは、DFAを実行している場合は機能しますが、NFAには複数の有効なパスが含まれる可能性があります。

あなたが持っている2つのオプション(私はもっとあると確信しています):

1)NFAエバリュエーターを実装する:これには、現在の状態のセットを追跡し、各入力文字を各状態に対して評価することが含まれます。文字列が読み取られると、最終状態のいずれかがセットに含まれている場合、それは完了です。

2)NFAをDFAに変換します。これは、基本的に同じセットロジックを構築し、新しい状態の遷移を評価する必要があるため、より難しいアプローチです。

于 2012-05-16T22:15:38.767 に答える