確定有限狀態(tài)自動(dòng)機(jī)

確定優(yōu)先狀態(tài)自動(dòng)機(jī)(Deterministic Finite Automation, DFA)是一種計(jì)算模型手销。它包含一系列狀態(tài)廊佩,這些狀態(tài)中:

  • 有一個(gè)特殊的狀態(tài)缤至,被稱(chēng)作初始狀態(tài)
  • 還有一系列狀態(tài)被稱(chēng)為接受狀態(tài)碎绎,它們組成了一個(gè)特殊的集合略步。其中透敌,一個(gè)狀態(tài)可能既是初始狀態(tài)盯滚,也是接受狀態(tài)踢械。

起初,這個(gè)自動(dòng)機(jī)處于初始狀態(tài)魄藕。隨后内列,它順序地讀取字符串中的每一個(gè)字符,并根據(jù)當(dāng)前狀態(tài)和讀入的字符背率,按照某個(gè)事先約定好的轉(zhuǎn)移規(guī)則话瞧,從當(dāng)前狀態(tài)轉(zhuǎn)移到下一個(gè)狀態(tài);當(dāng)狀態(tài)轉(zhuǎn)移完成后寝姿,它就讀取下一個(gè)字符交排。當(dāng)字符串全部讀取完畢后,如果自動(dòng)機(jī)處于某個(gè)接受狀態(tài)饵筑,則判定該字符串被接受埃篓;否則囊蓝,判定該字符串被拒絕盾舌。

確定優(yōu)先狀態(tài)自動(dòng)機(jī)-01.jpg

如果輸入的過(guò)程中某一步轉(zhuǎn)移失敗了回梧,即不存在對(duì)應(yīng)的轉(zhuǎn)移規(guī)則枝恋,此時(shí)計(jì)算將提前中止淑际。在這種情況下我們也判定該字符串被拒絕创坞。

確定有限狀態(tài)自動(dòng)機(jī)總是能夠回答某種形式的對(duì)于給定的輸入字符串S异吻,判斷其是否滿(mǎn)足條件P的問(wèn)題唱凯。

確定有限狀態(tài)自動(dòng)機(jī)驅(qū)動(dòng)的編程桨仿,可以被看做一種暴力枚舉方法的延伸:它窮盡了在任何一種情況下睛低,對(duì)應(yīng)任何的輸入,需要做的事情服傍。

自動(dòng)機(jī)在計(jì)算機(jī)科學(xué)領(lǐng)域有著廣泛的應(yīng)用钱雷。在算法領(lǐng)域,它與大名鼎鼎的字符串查找算法KMP算法有著密切的關(guān)聯(lián)吹零;在工程領(lǐng)域罩抗,它是實(shí)現(xiàn)正則表達(dá)式的基礎(chǔ)。

劍指 Offer 20. 表示數(shù)值的字符串為例:

class Solution {
    public boolean isNumber(String s) {
        Map<State, Map<CharType, State>> transfer = new HashMap<>();
        transfer.put(State.STATE_INITIAL, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_SPACE, State.STATE_INITIAL);
                    put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
                    put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
                    put(CharType.CHAR_SIGN, State.STATE_INT_SIGN);
                }}
        );
        transfer.put(State.STATE_INT_SIGN, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
                    put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
                }}
        );
        transfer.put(State.STATE_INTEGER, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
                    put(CharType.CHAR_EXP, State.STATE_EXP);
                    put(CharType.CHAR_POINT, State.STATE_POINT);
                    put(CharType.CHAR_SPACE, State.STATE_END);
                }}
        );
        transfer.put(State.STATE_POINT, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
                    put(CharType.CHAR_EXP, State.STATE_EXP);
                    put(CharType.CHAR_SPACE, State.STATE_END);
                }}
        );
        transfer.put(State.STATE_POINT_WITHOUT_INT, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
                }}
        );
        transfer.put(State.STATE_FRACTION, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
                    put(CharType.CHAR_EXP, State.STATE_EXP);
                    put(CharType.CHAR_SPACE, State.STATE_END);
                }}
        );
        transfer.put(State.STATE_EXP, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
                    put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
                }}
        );
        transfer.put(State.STATE_EXP_SIGN, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
                }}
        );
        transfer.put(State.STATE_EXP_NUMBER, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
                    put(CharType.CHAR_SPACE, State.STATE_END);
                }}
        );
        transfer.put(State.STATE_END, new HashMap<CharType, State>() {{
                    put(CharType.CHAR_SPACE, State.STATE_END);
                }}
        );

        int len = s.length();
        State state = State.STATE_INITIAL;

        for (int i = 0; i < len; i++) {
            CharType type = toCharType(s.charAt(i));
            if (!transfer.get(state).containsKey(type)) return false;
            else state = transfer.get(state).get(type);
        }

        return state == State.STATE_INTEGER || state == State.STATE_POINT || state == State.STATE_END || state == State.STATE_FRACTION || state == State.STATE_EXP_NUMBER;
    }

    public CharType toCharType(char c) {
        if (c >= '0' && c <= '9') return CharType.CHAR_NUMBER;
        if (c == 'e' || c == 'E') return CharType.CHAR_EXP;
        if (c == '.') return CharType.CHAR_POINT;
        if (c == '+' || c == '-') return CharType.CHAR_SIGN;
        if (c == ' ') return CharType.CHAR_SPACE;
        return CharType.CHAR_ILLEGAL;
    }

    enum State {
        STATE_INITIAL,
        STATE_INT_SIGN,
        STATE_INTEGER,
        STATE_POINT,
        STATE_POINT_WITHOUT_INT,
        STATE_FRACTION,
        STATE_EXP,
        STATE_EXP_SIGN,
        STATE_EXP_NUMBER,
        STATE_END
    }

    enum CharType {
        CHAR_NUMBER,
        CHAR_EXP,
        CHAR_POINT,
        CHAR_SIGN,
        CHAR_SPACE,
        CHAR_ILLEGAL
    }
}

狀態(tài)一定要定義好灿椅,小數(shù)后的整數(shù)和小數(shù)的前的整數(shù)是不一致的套蒂,需要使用不同的狀態(tài)STATE_INTEGERSTATE_FRACTION

參考文獻(xiàn):

  1. 表示數(shù)值的字符串
  2. 淺談DFA確定有限狀態(tài)自動(dòng)機(jī)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茫蛹,隨后出現(xiàn)的幾起案子操刀,更是在濱河造成了極大的恐慌,老刑警劉巖婴洼,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骨坑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡柬采,警方通過(guò)查閱死者的電腦和手機(jī)欢唾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)且警,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人礁遣,你說(shuō)我怎么就攤上這事振湾。” “怎么了亡脸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵押搪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我浅碾,道長(zhǎng)大州,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任垂谢,我火速辦了婚禮厦画,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滥朱。我一直安慰自己根暑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布徙邻。 她就那樣靜靜地躺著排嫌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缰犁。 梳的紋絲不亂的頭發(fā)上淳地,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音帅容,去河邊找鬼颇象。 笑死,一個(gè)胖子當(dāng)著我的面吹牛并徘,可吹牛的內(nèi)容都是我干的遣钳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼麦乞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蕴茴!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起路幸,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荐开,失蹤者是張志新(化名)和其女友劉穎付翁,沒(méi)想到半個(gè)月后简肴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡百侧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年砰识,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了能扒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辫狼,死狀恐怖初斑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情膨处,我是刑警寧澤见秤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站真椿,受9級(jí)特大地震影響鹃答,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜突硝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一测摔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧解恰,春花似錦锋八、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腐宋,卻和暖如春樊销,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脏款。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工围苫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撤师。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓剂府,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親剃盾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腺占,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容