• DFA



    layout: post
    title: "DFA"
    date: 2017-10-8 15:52:00 +0800
    categories: Algorithm
    tags: DFA
    author: SteveDevin

    mathjax: true

    • content
      {:toc}

    最近编译原理课学了DFA, 想起去年暑假学的DFA模式串匹配还没写过, 就趁机写一下了

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    const int LETTERS = 26;
    const int maxn = 200 + 2;
    
    struct TreeNode
    {
        TreeNode* child[LETTERS];
        TreeNode* prev;
        bool badNode;
    
        TreeNode(bool bad = false, TreeNode *p = NULL):badNode(bad), prev(p)
        {
            memset(child, 0, sizeof(child
        }
    }Tree[maxn];
    int nTreeNode = 0;
    
    void BuildTree(const char *s, TreeNode *p)
    {
        for(int i = 0; s[i]; i++)
        {
            if(!p->child[s[i] - 'a'])
                p->child[s[i] - 'a'] = Tree + nTreeNode++;
            p = p->child[s[i] - 'a'];
        }
        p->badNode = true;
    }
    
    void BuildDfa(TreeNode *Tree)
    {
        for(int i = 0; i < LETTERS; i++)
            Tree[0].child[i] = Tree + 1;
        Tree[0].prev = NULL;
        Tree[1].prev = Tree;
    
        deque<TreeNode *> q;
        q.push_back(Tree + 1);
    
        while(!q.empty())
        {
            TreeNode *pRoot = q.front();
            q.pop_front();
    
            for(int i = 0; i < LETTERS; i++)
            {
                TreeNode *p = pRoot->child[i];
                if(p)
                {
                    TreeNode *pPrev = pRoot->prev;
                    while(pPrev)
                    {
                        if(pPrev->child[i])
                        {
                            p->prev = pPrev->child[i];
                            if(p->prev->badNode) p->badNode = true;
                            break;
                        } else pPrev = pPrev->prev;
                    }
                    q.push_back(p);
                }
            }
        }
    }
    
    bool SearchDfa(TreeNode *Tree, const char *s)
    {
        TreeNode *p = Tree + 1;
    
        for(int i = 0; s[i]; i++)
        {
            while(true)
            {
                if(p->child[s[i] - 'a'])
                {
                    p = p->child[s[i] - 'a'];
    
                    if(p->badNode) return true;
                    break;
                }else p = p->prev;
            }
        }
        return false;
    }
    
    int main()
    {
        int N, M;
        cin >> N >> M;
    
        nTreeNode = 2;
    
        for(int i = 0; i < N; i++)
        {
            string s;
            cin >> s;
            BuildTree(s.c_str(), Tree + 1);
        }
    
        BuildDfa(Tree);
    
        for(int i = 0; i < M; i++)
        {
            string s;
            cin >> s;
            cout << (SearchDfa(Tree, s.c_str()) ? "True" : "False") << endl;
        }
    
        system("pause");
    }
    

    测试结果:

    2 2
    abc
    def
    deababcdef
    True
    deababb
    False
    

    写一个可以求出具体位置的版本(正确性待验证):

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <deque>
    using namespace std;
    
    // !!!!  input range in 'a' to 'z'
    
    const int maxn = 200 + 2;
    const int LETTERS = 26;
    
    struct TreeNode {
        TreeNode *child[LETTERS];
        TreeNode *prev;
        bool badNode;
        int deep;
    
        TreeNode() :prev(NULL), badNode(false), deep(0)
        {
            memset(child, 0, sizeof(child));
        }
    }Tree[maxn];
    int nTreeNode = 0;
    
    void BuildTree(TreeNode *pRoot, char *s)
    {
        for (int i = 0; s[i]; i++)
        {
            if (!pRoot->child[s[i] - 'a'])
                pRoot->child[s[i] - 'a'] = Tree + nTreeNode++;
            pRoot->child[s[i] - 'a']->deep = pRoot->deep + 1;
            pRoot = pRoot->child[s[i] - 'a'];
        }
        pRoot->badNode = true;
    }
    
    void BuildDfa(TreeNode *Tree)
    {
        for (int i = 0; i < LETTERS; i++)
            Tree->child[i] = Tree + 1;
        Tree[0].prev = NULL;
        Tree[1].prev = Tree;
    
        deque<TreeNode *> q;
        q.push_back(Tree + 1);
    
        while (!q.empty())
        {
            TreeNode *pRoot = q.front();
            q.pop_front();
    
            for (int i = 0; i < LETTERS; i++)
            {
                if (pRoot->child[i])
                {
                    TreeNode *pPrev = pRoot->prev;
                    while (pPrev)
                    {
                        if (pPrev->child[i])
                        {
                            pRoot->child[i]->prev = pPrev->child[i];
                            if (pRoot->child[i]->prev->badNode)
                            {
                                pRoot->child[i]->badNode = true;
                            }
                            break;
                        }else pPrev = pPrev->prev;
                    }
                    q.push_back(pRoot->child[i]);
                }
            }
        }
    }
    
    int SearchDfa(TreeNode *Tree, char *s)
    {
        TreeNode *p = Tree + 1;
        for (int i = 0; s[i]; i++)
        {
            while (true)
            {
                if (p->child[s[i] - 'a'])
                {
                    p = p->child[s[i] - 'a'];
                    if (p->badNode) return i - p->deep + 1;
                    break;
                }p = p->prev;
            }
        }
        return -1;
    }
    
    int main()
    {
        int N, M;
        nTreeNode = 2;
        scanf("%d%d", &N, &M);
    
        char s[maxn];
        for (int i = 0; i < N; i++)
        {
            scanf("%s", s);
            BuildTree(Tree + 1, s);
        }
    
        BuildDfa(Tree);
    
        for (int i = 0; i < M; i++)
        {
            scanf("%s", s);
            int ret = SearchDfa(Tree, s);
            if (ret < 0)
                cout << "NOT FOUND" << endl;
            else cout << ret << endl;
        }
    }
    
    
  • 相关阅读:
    并发编程---守护进程
    并发编程---Process对象的其他属性或方法
    并发编程---开启进程方式---查看进程pid
    并发编程---操作系统
    ie浏览器的css bug
    链接内的图片与文字如何对齐?
    inline元素特性
    最大流EK算法模板
    数据结构 链式表
    运算表达式 栈应用
  • 原文地址:https://www.cnblogs.com/QQ-1615160629/p/DFA.html
Copyright © 2020-2023  润新知