青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-91  評論-137  文章-0  trackbacks-0

上一篇我們已經得到了一個完整的ε-NFA,下面來說說如何將ε-NFA轉換為DFA(確定有限自動機)。

DFA的狀態

在DFA中,某個狀態對應到ε-NFA中的若干狀態,應此我們將會得到下面這樣的一個結構。

 

        struct DFA_State
        {
            set<EpsilonNFA_State*> content;
            bool                   bFlag;
#ifdef _DEBUG
            uint                   idx;
#endif

            DFA_State(const set<EpsilonNFA_State*>& x) : content(x), bFlag(false)
            {
#ifdef _DEBUG
                idx = inc();
#endif
            }

            inline const bool operator==(const DFA_State& x)const
            {
                if (&x == this) return true;

                return content == x.content;
            }

#ifdef _DEBUG
            inline uint inc()
            {
                static uint i = 0;
                return i++;
            }
#endif
        };

 

可以看到,為了調試方便我們在結構中定義了狀態的唯一ID以及對應到ε-NFA狀態的集合和一個標記位。

DFA的邊

根據上一篇的經驗,不難想到DFA的邊應該是什么樣的,下面直接給出代碼,不做說明。

 

        struct DFA_Edge
        {
            struct
            {
                Char_Type   char_value;
                String_Type string_value;
            }data;

            enum Edge_Type
            {
                TUnknown = 0,
                TNot     = 1,
                TChar    = 2,
                TString  = 4
            };

            uchar edge_type;

            DFA_State* pFrom;
            DFA_State* pTo;

            DFA_Edge(const Char_Type& x, bool bNot, DFA_State* pFrom, DFA_State* pTo) : pFrom(pFrom), pTo(pTo)
            {
                data.char_value = x;
                edge_type = bNot ? (TChar | TNot) : TChar;
            }

            DFA_Edge(const String_Type& x, bool bNot, DFA_State* pFrom, DFA_State* pTo) : pFrom(pFrom), pTo(pTo)
            {
                data.string_value = x;
                edge_type = bNot ? (TString | TNot) : TString;
            }

            inline const bool isNot()const
            {
                return (edge_type & TNot) == TNot;
            }

            inline const bool isChar()const
            {
                return (edge_type & TChar) == TChar;
            }

            inline const bool isString()const
            {
                return (edge_type & TString) == TString;
            }

            const Edge_Type edgeType()const
            {
                if (isChar()) return TChar;
                else if (isString()) return TString;
                else return TUnknown;
            }

            const bool operator<(const DFA_Edge& x)const
            {
                return (ulong)pFrom + pTo < (ulong)x.pFrom + x.pTo;
            }

            const bool operator==(const DFA_Edge& x)const
            {
                return pFrom == x.pFrom && pTo == x.pTo;
            }
        };

 

 

由于DFA中不存在ε邊,應此DFA將會存在若干個結束狀態,但他只有一個開始狀態

 

DFA_State*      pDFAStart;
set<DFA_State*> pDFAEnds;
set<DFA_Edge>   dfa_Edges;

 

 

為了下一步分析的高效,以后可能會將這里的dfa_Edges同樣修改為hashmap。

至此DFA所要用到的兩個結構迅速的介紹完了。

子集構造算法

通過各種資料,我們不難發現,從ε-NFA轉換到DFA的過程中,最常用就是子集構造算法。子集構造算法的主要思想是讓DFA的每個狀態對應NFA的一個狀態集。這個DFA用它的狀態去記住NFA在讀輸入符號后達到的所有狀態。(引自編譯原理)其算法如下

 

輸入:一個NFA N。
輸出:一個接受同樣語言的DFA D。
方法:
1.求取ε-NFA初始狀態的ε閉包作為DFA的起始狀態,并將這個狀態加入集合C中,且它是未標記的。同時記錄它的向后字符集。
2.從集合C中取出一個未被標記的子集T和其對應的字符集,標記子集T。
3.使用上一步取出的字符集通過狀態轉移函數求出轉移后的狀態集M。
4.求取上一步得到的狀態集M的ε閉包U
5.如果U不在集合C中則將U作為未被標記的子集加入C中,同時記錄它的向后字符集。檢查狀態U中是否存在NFA中的終結狀態,若存在則將狀態U加入到pDFAEnds中。
重復2,3,4,5部直至集合C中不存在未被標記的狀態。

ε閉包

ε閉包是指從某個狀態起只經過ε邊達到的其他狀態的集合,同時這個狀態也屬于這個集合中。其算法如下

 

輸入:狀態集k。
輸出:狀態集U和其所對應的向后字符集。
方法:
1.遍歷狀態集k中的每個狀態k'。
2.若k'不存在于結果狀態集U中,將k'插入U中。
3.建立一個臨時集合tmp,并將k'插入其中。
4.從臨時集合tmp中取出一個狀態p。
5.取出所有從p出發的邊,若這條邊是ε邊,且抵達狀態不在結果狀態集U中,將抵達的狀態分別插入結果狀態集U和臨時集合tmp中。若這條邊是字符集的邊且這條邊所對應的字符不在向后字符集中,則將向后字符插入向后字符集中。
6.將狀態p從臨時集合tmp中刪除。
循環4,5,6部直至tmp中不存在任何狀態為止。

 

 

由于在生成ε-NFA時不存在只有ε邊的循環,應此這里不會產生死循環。下面給出具體的代碼

 

        void epsilonClosure(const set<EpsilonNFA_State*>& k, EpsilonClosureInfo& info)
        {
            for (typename set<EpsilonNFA_State*>::const_iterator i = k.begin(), m = k.end(); i != m; ++i)
            {
                info.states.insert(*i);
                set<EpsilonNFA_State*> tmp;
                tmp.insert(*i);
                while (!tmp.empty())
                {
                    EpsilonNFA_State* pState = *tmp.begin();
                    for (typename vector<EpsilonNFA_Edge>::const_iterator j = epsilonNFA_Edges[pState].begin(), n = epsilonNFA_Edges[pState].end(); j != n; ++j)
                    {
                        if (j->isEpsilon())
                        {
                            if (info.states.insert(j->pTo).second) tmp.insert(j->pTo);
                        }
                        else if (j->isChar()) info.chars.insert(pair<Char_Type, bool>(j->data.char_value, j->isNot()));
                        else if (j->isString()) info.strings.insert(pair<String_Type, bool>(j->data.string_value, j->isNot()));
                    }
                    tmp.erase(pState);
                }
            }
        }

 

 

其中用到的EpsilonClosureInfo結構為

 

        struct EpsilonClosureInfo
        {
            set<EpsilonNFA_State*>        states;
            set<pair<Char_Type, bool> >   chars;
            set<pair<String_Type, bool> > strings;

            EpsilonClosureInfo() {}

            EpsilonClosureInfo(const set<EpsilonNFA_State*>& states,
                               const set<pair<Char_Type, bool> >& chars,
                               const set<pair<String_Type, bool> >& strings)
                               : states(states)
                               , chars(chars)
                               , strings(strings) {}

            EpsilonClosureInfo(const EpsilonClosureInfo& x)
            {
                states  = x.states;
                chars   = x.chars;
                strings = x.strings;
            }
        };

 

需要保存的是狀態集和向后字符集。

狀態轉移函數

通過狀態轉移函數,輸入一個集合T和一個字符a將可得到所有通過T中的每一個狀態和a邊所能達到的狀態的集合。應此代碼如下

 

        set<EpsilonNFA_State*> move(const DFA_State& t, const Char_Type& c, bool bNot)
        {
            set<EpsilonNFA_State*> result;
            for (typename set<EpsilonNFA_State*>::const_iterator i = t.content.begin(), m = t.content.end(); i != m; ++i)
            {
                for (typename vector<EpsilonNFA_Edge>::const_iterator j = epsilonNFA_Edges[*i].begin(), n = epsilonNFA_Edges[*i].end(); j != n; ++j)
                {
                    if (j->isChar() && j->data.char_value == c && j->isNot() == bNot) result.insert(j->pTo);
                }
            }
            return result;
        }

        set<EpsilonNFA_State*> move(const DFA_State& t, const String_Type& s, bool bNot)
        {
            set<EpsilonNFA_State*> result;
            for (typename set<EpsilonNFA_State*>::const_iterator i = t.content.begin(), m = t.content.end(); i != m; ++i)
            {
                for (typename vector<EpsilonNFA_Edge>::const_iterator j = epsilonNFA_Edges[*i].begin(), n = epsilonNFA_Edges[*i].end(); j != n; ++j)
                {
                    if (j->isString() && j->data.string_value == s && j->isNot() == bNot) result.insert(j->pTo);
                }
            }
            return result;
        }

 

 

為了分別支持Char_Type和String_Type的字符我們定義了兩個move函數。

最后我們給出子集構造算法的代碼

 

        void buildDFA()
        {
            set<EpsilonNFA_State*> start;
            start.insert(pEpsilonStart);

            typedef pair<DFA_State*, EpsilonClosureInfo> c_type;

            map<size_t, list<c_type> > c;
            queue<c_type> c2;

            pDFAStart = DFA_State_Alloc::allocate();
            EpsilonClosureInfo info;
            epsilonClosure(start, info);
            construct(pDFAStart, info.states);

            c_type ct(pDFAStart, info);
            c[info.states.size()].push_back(ct);
            c2.push(ct);

            if (isEndDFAStatus(pDFAStart)) pDFAEnds.insert(pDFAStart);
            context.dfa_States.insert(pDFAStart);

            while (!c2.empty())
            {
                DFA_State* t = c2.front().first;
                set<pair<Char_Type, bool> > chars = c2.front().second.chars;
                set<pair<String_Type, bool> > strings = c2.front().second.strings;
                t->bFlag = true;

                for (typename set<pair<Char_Type, bool> >::const_iterator i = chars.begin(), m = chars.end(); i != m; ++i)
                {
                    EpsilonClosureInfo info;
                    epsilonClosure(move(*t, i->first, i->second), info);

                    DFA_State* p = getDFAState(info.states, c);
                    if (p) // 如果這個狀態已存在
                    {
                        dfa_Edges.insert(DFA_Edge(i->first, i->second, t, p));
                    }
                    else
                    {
                        DFA_State* pState = DFA_State_Alloc::allocate();
                        construct(pState, info.states);
                        context.dfa_States.insert(pState);

                        if (isEndDFAStatus(pState)) pDFAEnds.insert(pState);

                        c_type ct(pState, info);
                        c[info.states.size()].push_back(ct);
                        c2.push(ct);

                        dfa_Edges.insert(DFA_Edge(i->first, i->second, t, pState));
                    }
                }

                for (typename set<pair<String_Type, bool> >::const_iterator i = strings.begin(), m = strings.end(); i != m; ++i)
                {
                    EpsilonClosureInfo info;
                    epsilonClosure(move(*t, i->first, i->second), info);

                    DFA_State* p = getDFAState(info.states, c);
                    if (p) // 如果這個狀態已存在
                    {
                        dfa_Edges.insert(DFA_Edge(i->first, i->second, t, p));
                    }
                    else
                    {
                        DFA_State* pState = DFA_State_Alloc::allocate();
                        construct(pState, info.states);
                        context.dfa_States.insert(pState);

                        if (isEndDFAStatus(pState)) pDFAEnds.insert(pState);

                        c_type ct(pState, info);
                        c[info.states.size()].push_back(ct);
                        c2.push(ct);

                        dfa_Edges.insert(DFA_Edge(i->first, i->second, t, pState));
                    }
                }
                c2.pop();
            }
        }

 

 

尾聲

同樣我們來編寫一個函數來打印出DFA。

 

        void printDFA()
        {
            printf("---------- DFA Start ----------\n");
            set<DFA_State*> tmp;
            for (typename set<DFA_Edge>::const_iterator i = dfa_Edges.begin(), m = dfa_Edges.end(); i != m; ++i)
            {
                printf("%03d -> %03d", i->pFrom->idx, i->pTo->idx);
                switch (i->edgeType())
                {
                case DFA_Edge::TChar:
                    printf("(%c)", i->data.char_value);
                    break;
                case DFA_Edge::TString:
                    printf("(%s)", i->data.string_value.c_str());
                    break;
                default:
                    break;
                }
                if (i->isNot()) printf("(not)");
                printf("\n");
                tmp.insert(i->pFrom);
                tmp.insert(i->pTo);
            }

            printf("start: %03d -> ends: ", pDFAStart->idx);
            for (typename set<DFA_State*>::const_iterator i = pDFAEnds.begin(), m = pDFAEnds.end(); i != m; ++i)
            {
                printf("%03d ", (*i)->idx);
            }
            printf("\n");
#if DEBUG_LEVEL == 3
            printf("-------------------------------\n");

            for (typename set<DFA_State*>::const_iterator i = tmp.begin(), m = tmp.end(); i != m; ++i)
            {
                printf("State: %03d\n", (*i)->idx);
                for (typename set<EpsilonNFA_State*>::const_iterator j = (*i)->content.begin(), n = (*i)->content.end(); j != n; ++j)
                {
                    printf("%03d ", (*j)->idx);
                }
                printf("\n");
            }
#endif
            printf("----------- DFA End -----------\n");
        }

 

 

最后我們加入測試代碼

 

Rule_Type::Context context;
Rule_Type a('a', context), b('b', context), d('d', context);
Rule_Type result = (a - d).opt() + (+b | !(a + b));
result.buildDFA();

#ifdef _DEBUG
result.printEpsilonNFA();
result.printDFA();
#endif

 

 

可打印出如下內容

DFA

畫成圖如下

DFA圖

完整的代碼可到http://code.google.com/p/qlanguage下載

posted on 2013-02-23 23:30 lwch 閱讀(2893) 評論(0)  編輯 收藏 引用 所屬分類: QLanguage
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美精品九九| 欧美一级大片在线免费观看| av不卡在线| 亚洲精品色图| 亚洲激情六月丁香| 日韩一级免费| 欧美亚洲网站| 麻豆成人在线观看| 亚洲日本欧美天堂| 日韩视频在线一区二区三区| 一区二区动漫| 久久大逼视频| 欧美日本在线观看| 国产精品亚洲激情| 1024亚洲| 亚洲欧美一区二区三区久久| 久久综合伊人77777蜜臀| 亚洲国产小视频在线观看| 日韩视频免费观看| 久久精品官网| 欧美日韩中文字幕综合视频| 国产一区二区三区在线观看网站 | 久久久久久网站| 麻豆91精品| 国产精品久久久久久久7电影| 国精品一区二区| 一区二区三区四区五区在线| 极品av少妇一区二区| 亚洲大胆在线| 亚洲一级二级在线| 欧美成人国产| 国产在线播精品第三| 99国产精品久久久久老师| 久久国产精品久久久| 亚洲精品久久久久久久久久久| 亚洲欧美日韩精品久久奇米色影视| 美女精品网站| 国产在线精品一区二区中文| 亚洲与欧洲av电影| 亚洲国产天堂久久综合| 久久久久久久久岛国免费| 国产精品国产三级国产普通话99| 激情成人综合网| 欧美在线亚洲一区| 99亚洲精品| 欧美激情综合网| 亚洲电影毛片| 久久综合狠狠| 午夜在线精品偷拍| 国产精品自在在线| 亚洲一区在线免费观看| 亚洲狼人综合| 欧美日韩成人综合| 亚洲美女视频| 91久久香蕉国产日韩欧美9色| 美女日韩在线中文字幕| 亚洲电影下载| 欧美激情免费观看| 蜜桃av综合| 亚洲精品少妇| 亚洲精品免费在线播放| 欧美激情精品久久久久久变态| 亚洲第一区在线| 欧美激情精品久久久久| 另类专区欧美制服同性| 亚洲国产第一页| 亚洲第一色在线| 欧美日韩高清在线播放| 亚洲伊人网站| 午夜天堂精品久久久久| 国产在线欧美| 亚洲电影中文字幕| 欧美日韩一区不卡| 欧美一区二区三区四区在线观看| 亚洲欧美激情诱惑| 激情伊人五月天久久综合| 欧美成人精品福利| 欧美精品手机在线| 亚洲在线不卡| 久久av二区| 亚洲美女尤物影院| 亚洲视频一二区| 曰本成人黄色| 99精品欧美一区二区三区| 国产精品人人爽人人做我的可爱 | 亚洲欧洲精品一区二区| 亚洲丰满在线| 欧美午夜免费| 久久久久久一区二区三区| 麻豆精品视频在线观看| 在线视频你懂得一区| 午夜国产一区| 亚洲黄色精品| 亚洲一区二区三区在线视频| 影音欧美亚洲| 亚洲无毛电影| 亚洲经典在线| 亚洲欧美国产精品va在线观看| 亚洲国产精品一区在线观看不卡| 99视频在线精品国自产拍免费观看| 国产在线拍偷自揄拍精品| 亚洲精品乱码久久久久久按摩观| 国产精品一区二区你懂得| 欧美成人一区在线| 国产欧美一区二区三区久久人妖| 欧美激情视频一区二区三区在线播放| 欧美网站在线观看| 欧美激情一区二区久久久| 国产精品性做久久久久久| 欧美激情亚洲一区| 国产在线观看91精品一区| 夜色激情一区二区| 亚洲精品综合| 久久伊人免费视频| 久久九九99视频| 国产精品羞羞答答| 一区二区三区四区国产| 亚洲乱码视频| 免费亚洲电影| 久久理论片午夜琪琪电影网| 欧美午夜国产| 亚洲精品字幕| 999亚洲国产精| 欧美二区乱c少妇| 欧美sm极限捆绑bd| 在线观看欧美日本| 久久久久久9| 另类国产ts人妖高潮视频| 国产一区二区三区丝袜| 亚洲欧美在线一区| 欧美在线播放| 国产视频亚洲精品| 欧美一区二区在线免费播放| 欧美夜福利tv在线| 国产精品自拍一区| 欧美亚洲一区三区| 久久乐国产精品| 韩国三级在线一区| 久久米奇亚洲| 欧美激情女人20p| 日韩一级黄色片| 欧美日在线观看| 亚洲午夜精品视频| 欧美一区二区三区在线看| 国产欧美日韩精品一区| 欧美伊人久久久久久久久影院 | 亚洲黄色在线视频| 亚洲美女精品成人在线视频| 欧美伦理在线观看| 亚洲一区3d动漫同人无遮挡| 久久精品视频在线播放| 一区二区三区日韩欧美| 国产精品入口麻豆原神| 久久亚洲视频| 亚洲电影一级黄| 欧美激情一区二区三区在线| 日韩亚洲在线观看| 先锋资源久久| 激情综合中文娱乐网| 欧美黄在线观看| 亚洲欧美日韩专区| 美女日韩在线中文字幕| 99在线|亚洲一区二区| 国产精品视频福利| 久久网站热最新地址| 亚洲美女在线一区| 久久欧美中文字幕| av不卡在线| 国产在线视频欧美| 欧美日韩视频在线一区二区 | 国产伦理精品不卡| 老司机免费视频一区二区三区| 亚洲日韩欧美视频| 久久精品国产精品亚洲精品| 亚洲欧洲精品一区二区三区 | 老司机67194精品线观看| 一级成人国产| 欧美不卡激情三级在线观看| 中文欧美日韩| 亚洲激情视频在线| 国产欧美一区二区精品仙草咪| 欧美aⅴ99久久黑人专区| 午夜精品久久| 亚洲精品综合久久中文字幕| 老巨人导航500精品| 亚洲男人影院| 亚洲美女一区| 亚洲高清视频在线观看| 国产香蕉97碰碰久久人人| 欧美日韩视频专区在线播放 | 91久久精品久久国产性色也91| 久久精品30| 性一交一乱一区二区洋洋av| 一区二区三区久久网| 亚洲第一综合天堂另类专| 国产日韩欧美综合精品| 国产精品国产三级国产aⅴ9色| 欧美精品乱人伦久久久久久| 麻豆91精品| 蜜桃av一区二区|