日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实现一个 DFA 正则表达式引擎 - 4. DFA 的最小化

發布時間:2024/9/5 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现一个 DFA 正则表达式引擎 - 4. DFA 的最小化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(正則引擎已完成,Github)

最小化 DFA 是引擎中另外一個略繁瑣的點(第一個是構建語法樹)。

基本思路是,先對 DFA 進行重命名,然后引入一個拒絕態 0,定義所有狀態經過非接受字符轉到狀態 0,0 接受所有字符轉換為自身。也就是說我們先建立一個轉換表,然后把第一行填寫為:

stateabcdefgh...
0000000000

再之后,我們講 DFA 的其余狀態從 1 開始重命名,填入狀態表。代碼實現如下:

// rename all statesfor (Set<NFAState> nfaState : oriDFATransitionMap.keySet()) {if (initStateAfterRenaming == -1 && nfaState.equals(initClosure)) {initStateAfterRenaming = renamingStateID; // record init state id}stateRenamingMap.put(nfaState, renamingStateID++);}renamedDFATransitionTable.put(0, newRejectState()); // the reject state 0finalFlags.put(0, false);// construct renamed dfa transition tablefor (Map.Entry<Set<NFAState>, Map<Character, Set<NFAState>>> entry : oriDFATransitionMap.entrySet()) {renamingStateID = stateRenamingMap.get(entry.getKey());int[] state = newRejectState();for (Map.Entry<Character, Set<NFAState>> row : entry.getValue().entrySet()) {state[row.getKey()] = stateRenamingMap.get(row.getValue());}renamedDFATransitionTable.put(renamingStateID, state);if (entry.getKey().contains(finalNFAState)) {finalFlags.put(renamingStateID, true);} else finalFlags.put(renamingStateID, false);}

這里有一個 finalFlags 用來記錄哪些 DFA 的終態包含了 NFA 的終態 1。(這些狀態都作為 DFA 的終態)

接下來,把所有狀態分為終態作為一個 group,非終態作為另一個 group:

// split states to final states and non-final statesMap<Integer, Integer> groupFlags = new HashMap<>();for (int i = 0; i < finalFlags.size(); i++) {boolean b = finalFlags.get(i);if (b) groupFlags.put(i, 0);else groupFlags.put(i, 1);}

我們定義任意 group 中的任意狀態的轉換規則為:接受某個字符轉移到某個 group(區別于轉換到某個狀態)。

不停地遍歷所有的 group,把同一個 group 中具有不同轉換規則的狀態分隔為不同的 group。

do { // splitting, group id is the final state idpreGroupTotal = groupTotal;for (int sensitiveGroup = 0; sensitiveGroup < preGroupTotal; sensitiveGroup++) {// <target group table, state id set>Map<Map<Integer, Integer>, Set<Integer>> invertMap = new HashMap<>();for (int sid = 0; sid < groupFlags.size(); sid++) { //use state id to iterateint group = groupFlags.get(sid);if (sensitiveGroup == group) {Map<Integer, Integer> targetGroupTable = new HashMap<>(CommonSets.ENCODING_LENGTH);for (char ch = 0; ch < CommonSets.ENCODING_LENGTH; ch++) {int targetState = renamedDFATransitionTable.get(sid)[ch];int targetGroup = groupFlags.get(targetState);targetGroupTable.put((int) ch, targetGroup);}Set<Integer> stateIDSet = invertMap.get(targetGroupTable);if (stateIDSet == null) {stateIDSet = new HashSet<>();invertMap.put(targetGroupTable, stateIDSet);}stateIDSet.add(sid); // gather all sids having the same target group table into this set}}boolean first = true;for (Set<Integer> stateIDSet : invertMap.values()) {if (first) {first = false;} else {for (int sid : stateIDSet) {groupFlags.put(sid, groupTotal);}groupTotal++;}}}} while (preGroupTotal != groupTotal);

如此分到不可再分,再把每一個 group 中的所有狀態合并為同一個狀態,這樣我們就得到了 group 個狀態,就完成了 DFA 的最小化。

接著是再次確定整個 DFA 的初態、終態和拒絕態。我們只要把包含這些狀態的 group 作為最小化之后的相應狀態就可以了。

// determine initial group stateis = groupFlags.get(initStateAfterRenaming);// determine reject group staters = groupFlags.get(0);// determine final group statesSet<Integer> finalGroupFlags = new HashSet<>();for (int i = 0, groupFlagsSize = groupFlags.size(); i < groupFlagsSize; i++) {Integer groupFlag = groupFlags.get(i);if (finalFlags.get(i)) {finalGroupFlags.add(groupFlag);}}fs = new boolean[groupTotal];for (int i = 0; i < groupTotal; i++) {fs[i] = finalGroupFlags.contains(i);}

最后一步是把 DFA 轉換為一個以數組形式存放的狀態表,就可以用來進行快速而準確的正則匹配了。

// construct the final transition tabletransitionTable = new int[groupTotal][];for (int groupID = 0; groupID < groupTotal; groupID++) {for (int sid = 0; sid < groupFlags.size(); sid++) {if (groupID == groupFlags.get(sid)) {int[] oriState = renamedDFATransitionTable.get(sid);int[] state = new int[CommonSets.ENCODING_LENGTH];for (char ch = 0; ch < CommonSets.ENCODING_LENGTH; ch++) {int next = oriState[ch];state[ch] = groupFlags.get(next);}transitionTable[groupID] = state;break;}}}

至此,我們的整個 DFA 正則表達式引擎就構建完成了。

之后我用一個 apache log 的正則做了一下性能測試,這個引擎的匹配速度比 JDK 自帶的正則要快至少一倍,還是有一定的實用性的,所以我把它放到了?Github?上,歡迎下載源碼。

個人水平有限,代碼中一定有不少尚待優化的地方,如有建議請不吝賜教。

轉載于:https://www.cnblogs.com/zbdzzg/p/4509326.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的实现一个 DFA 正则表达式引擎 - 4. DFA 的最小化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美无砖区| 女教师高潮黄又色视频 | 性一交一乱一乱一视频 | 韩国三级做爰视频 | 久草免费av| 天堂在线中文资源 | 亚洲自拍偷拍一区二区三区 | 18被视频免费观看视频 | 91丨国产丨白丝 | 国产一级爱 | 亚洲永久无码7777kkk | 福利在线一区二区三区 | www成人啪啪18软件 | 免费a视频 | 插插久久 | 日本视频中文字幕 | 黄色第一网站 | 黑人玩弄人妻一区二区三区免费看 | 91精品人妻一区二区三区四区 | 2025国产精品 | 探花国产精品一区二区 | 欧美高h视频 | 国产精品久久久久久久一区二区 | 羞羞漫画在线播放 | 日韩福利电影在线观看 | 黄色一级视频免费 | 波多野吉衣一区 | 天天干天天操天天插 | 沟厕沟厕近拍高清视频 | 成人综合网站 | www.好了av | 高hnp视频 | 夜夜看av | av女大全列表| 91精品国产高清一区二区三密臀 | 两个人看的www视频免费完整版 | 亚洲午夜无码久久久久 | 真实新婚偷拍xxxxx | 亚洲精品乱码久久久久久 | 欧美大奶在线 | 91免费视频大全 | 日韩av手机在线观看 | 97欧美视频 | 日韩有码在线观看 | 操操色| 久久伊人影院 | 双性娇喘浑圆奶水h男男漫画 | 18做爰免费视频网站 | 久草高清 | 欧美精品1区| eeuss鲁丝片一区二区三区 | 高清视频在线播放 | 91精品国产色综合久久不卡98 | 国产av无码专区亚洲a∨毛片 | 不卡的av在线播放 | 久久人| 天天综合久久综合 | 久久久久久一区二区 | 亚洲精品污一区二区三区 | 婷婷综合av| 国产777| 国产精品99久久久久久www | 欧美三级影院 | 日韩欧美成 | 97精品人妻一区二区三区在线 | aaaa黄色| 四虎影库永久在线 | 亚洲无吗在线观看 | 国产毛片久久久久久久 | 日韩一级片av | 久久亚洲一区 | 无遮挡在线 | 亚洲精品电影院 | 日韩黄片一区二区三区 | 亚洲伊人婷婷 | a∨鲁丝一区鲁丝二区鲁丝三区 | 免费看特级毛片 | 亚洲精品成人区在线观看 | 91久久精品无码一区二区 | 国产婷婷色一区二区三区 | 国产精品无码毛片 | 欧美黑人啪啪 | 国产精品乱码一区二三区小蝌蚪 | 激情亚洲天堂 | 国产做受视频 | 四虎av影院 | 91蝌蚪在线观看 | 欧美亚洲综合在线 | 一区二区成人免费视频 | 肉性天堂 | 国v精品久久久网 | 日韩一二三级 | 精品中文字幕在线 | 操穴网站 | 中文字幕在线观看1 | 天天色天天干天天色 | 久久久精品中文字幕 | 午夜视频一区 | 一级片在线观看免费 |