zoukankan      html  css  js  c++  java
  • GMOJ 3569. 正则表达式

     

     Input

    Output

    对于每一组数据,如果正则表达式r能表示字符串str,输出“Yes”,否则输出“No”。

    Solution

     考虑对于题目所给的正则表达式建一个自动机。

    设当前在处理 S[l...r] ,last 指向 当前自动机要继续扩展的点(ed)。

    1.串联

    last 向新增的 st 连一条空边,然后将 last 设为 ed

    2.单个字符a

    新建st、ed节点,然后连一条权值为此字符的边。

     

    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 是独立的;

    对于部分操作(例如2、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
    ", ch + 1)) {
            Mes(head, 0), Mes(h, 0), tot = 0;
            n = strlen(ch + 1);
            last_d = Insert(1, n);
            scanf("%s
    ", ch + 1);
            m = strlen(ch + 1);
            Mes(f, 0);
            puts(Dfs(last_d.st, 1) ? "Yes" : "No");
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    jvisualm 结合 visualGC 进行jvm监控,并分析垃圾回收
    linux 查看服务器cpu 与内存配置
    arthas 使用总结
    selinux contexts 安全上下文的临时更改
    Android 8.1 Doze模式分析(五) Doze白名单及Debug方式
    Window 任意窗口置顶软件Window TopMost Control
    Android ApkToolPlus一个可视化的跨平台 apk 分析工具
    SVN Please execute the 'Cleanup' command.
    Android 如何在64位安卓系统中使用32位SO库
    Android cmd命令查看apk是32位还是64位?
  • 原文地址:https://www.cnblogs.com/zhouzj2004/p/13510284.html
Copyright © 2011-2022 走看看