GMOJ 3569. 正則表達式

 

 Input正則表達式

Outputide

對於每一組數據,若是正則表達式r能表示字符串str,輸出「Yes」,不然輸出「No」。post

 

Solutionspa

 考慮對於題目所給的正則表達式建一個自動機。3d

設當前在處理 S[l...r] ,last 指向 當前自動機要繼續擴展的點(ed)。code

1.串聯blog

last 向新增的 st 連一條空邊,而後將 last 設爲 ed字符串

2.單個字符astring

新建st、ed節點,而後連一條權值爲此字符的邊。it

 

 

3." ( "

找到與之對應的")",新建一對st、ed節點,對於括號中間的字符串dg處理

 

4.並聯

將 last (當前的 ed)與 S[l...r]的 ed 連一條空邊,而後將 last 重設爲S[l...r]的 st

5. " + "

當前 last 指向的 ed 向對應 st 連一條空邊

6. " * "

第一步與 + 操做相同,但要多連一條 st -> ed 的空邊

7. 別忘了最後將連一條 last 到S[l...r]的 ed 的空邊哦~ 

PS:每次操做完後若是要更新 last 不要忘記,對於每個要處理的字符串S[l, r],它們的 last 是獨立的;

對於部分操做(例如二、3操做),實際上是伴隨着串聯操做的。

 

最後咱們須要判斷構造出來的自動機十分能構造出字符串 str,

設 f[i][j] 表示 str 匹配到第i位,自動機上匹配到 j是否可行,轉移顯然,注意空邊能夠直接轉移過去

最後看 f[n][ed] 是否爲1便可

 

 

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define N 100
#define M 1000

#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define Mes(a, x) memset(a, x, sizeof a)

struct EDGE { int next, to; char c; } edge[M + 1];

struct Edge { int next, to; } g[M + 1];

int head[M + 1], h[M + 1], f[N + 1][M + 1], Next[M + 1], pre[M + 1];

char ch[N + 1];

int tot = 0, n, m;

struct Arr { int st, ed; } last_d;

int cnt_edge = 0;
void Add(int u, int v, char c) { edge[ ++ cnt_edge ] = (EDGE) { head[u], v, c }, head[u] = cnt_edge; }

int cnt_g = 0;
void Add(int u, int v) { g[ ++ cnt_g ] = (Edge) { h[u], v }, h[u] = cnt_g; }

Arr Insert(int l, int r) {
    if (l > r) return (Arr) { 0, 0 };
    int st = ++ tot, ed = ++ tot;
    Next[ed] = st;
    if (l == r) {
        Add(st, ed, ch[l]);
        return (Arr) { st, ed };
    }
    int last = st;
    fo(i, l, r) {
        if (ch[i] == '(') {
            int s = 1;
            fo(j, i + 1, r) {
                s += ch[j] == ')' ? -1 : (ch[j] == '(' ? 1 : 0);
                if (! s) {
                    Arr d = Insert(i + 1, j - 1);
                    if (! d.st) break;
                    Add(last, d.st), pre[d.st] = last;
                    last = d.ed;
                    i = j;
                    break;
                }
            }
        } else if (ch[i] == '|') {
            Add(last, ed); last = st;
        } else if (ch[i] == '*') {
            Add(last, Next[last]), Add(Next[last], last);
        } else if (ch[i] == '+') {
            Add(last, Next[last]);
        } else if (ch[i] == ')') 
            continue;
        else {
            Arr d = Insert(i, i);
            Add(last, d.st), pre[d.st] = last; 
            last = d.ed;
        }
    }
    Add(last, ed);
    return (Arr) { st, ed };
}

bool Dfs(int t, int x) {
    if (t > m && x == last_d.ed) return 1;
    if (f[t][x]) return 0;
    f[t][x] = 1;
    if (t <= m) {
        for (int i = head[x]; i; i = edge[i].next)
            if (edge[i].c == ch[t] && Dfs(t + 1, edge[i].to))
                return 1;
    }
    for (int i = h[x]; i; i = g[i].next)
        if (Dfs(t, g[i].to))
            return 1;
    return 0;
}

int main() {

    while (~ scanf("%s\n", ch + 1)) {
        Mes(head, 0), Mes(h, 0), tot = 0;
        n = strlen(ch + 1);
        last_d = Insert(1, n);
        scanf("%s\n", ch + 1);
        m = strlen(ch + 1);
        Mes(f, 0);
        puts(Dfs(last_d.st, 1) ? "Yes" : "No");
    }

    return 0;
}
View Code
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息