zoukankan      html  css  js  c++  java
  • [板子]字符串-KMP与AC自动机

    KMP

    暴跳next

    luogu3375

    #include <bits/stdc++.h>
    
    const int N = 1e6 + 30; 
    
    int pos;
    int lena;
    int lenb;
    int nx[N];
    char a[N];
    char b[N];
    
    
    int main() 
    {
        std::cin >> a>> b;
        lena = std::strlen(a);
        lenb = std::strlen(b);
        for (int i = 1; i < lenb; ++i)
        {
            while (pos != 0 && b[pos] != b[i]) 
                pos = nx[pos];
            if (b[pos] == b[i]) 
                ++pos;
            nx[i + 1] = pos;
        }
        pos = 0;
        for (int i = 0; i < lena; ++i)
        {
            while (pos != 0 && b[pos] != a[i])
                pos = nx[pos];
            if (b[pos] == a[i]) 
                ++pos;
            if (pos == lenb)
                printf ("%d
    ", i - lenb + 2);
        }
        for (int i = 1; i <= lenb; ++i)
            printf ("%d ", nx[i]);
        printf ("
    ");
        return 0;
    }
    

    AC自动机

    tire树上暴跳fail

    详细学习请搜索yyb博客,讲的很好

    luogu3796

    #include <bits/stdc++.h>
    
    const int N = 1000000 + 30;
    
    int n;
    int tot;
    std::string s, str[N];
    
    struct AC
    {
        int fail;
        int end;
        int vis[28];
    }a[N];
    
    struct NODE
    {
        int num;
        int tot;
    }ans[N];
    
    bool operator <(NODE x, NODE y)
    {
        if (x.tot != y.tot)
            return x.tot > y.tot;
        else 
            return x.num < y.num;
    }
    
    inline void init(int num)
    {
        std::memset(a[num].vis, 0, sizeof(a[num].vis));
        a[num].fail = 0;
        a[num].end = 0;
    }
    
    inline void Insert(int num, std::string strr)
    {
        int now = 0;
        int len = strr.size();
        for (int i = 0; i < len; ++i)
        {
            if (a[now].vis[strr[i] - 'a'] == 0)
            {
                a[now].vis[strr[i] - 'a'] = ++tot;
                init(tot);
            }
            now = a[now].vis[strr[i] - 'a'];
        }
        a[now].end = num;
    }
    
    inline void Work_Fail()
    {
        int now = 0;
        std::queue < int > q;
        for (int i = 0; i < 26; ++i)
        {
            if (a[now].vis[i] != 0)
            {
                a[a[now].vis[i]].fail = 0;
                q.push(a[now].vis[i]);
            }
        }
        while (!q.empty())
        {
            now = q.front();
            q.pop();
            for (int i = 0; i < 26; ++i)
            {
                if (a[now].vis[i] != 0)
                {
                    a[a[now].vis[i]].fail = a[a[now].fail].vis[i];
                    q.push(a[now].vis[i]);
                }
                else
                    a[now].vis[i] = a[a[now].fail].vis[i];
            }    
        }
    }
    
    inline void Work_Ans(std::string strr)
    {
        int now = 0;
        int len = strr.size();
        for (int i = 0; i < len; ++i)
        {
            now = a[now].vis[strr[i] - 'a'];
            for (int t = now; t != 0; t = a[t].fail)
                ++ans[a[t].end].tot;
        }
    }
    
    int main() 
    {
        while (37373737)
        {
            std::cin >> n;
            if (n == 0)
                return n;
            tot = 0;
            init(0);
            for (int i = 1; i <= n; ++i)
            {
                std::cin >> str[i];
                ans[i] = (NODE){i, 0};
                Insert(i, str[i]);
            }
            Work_Fail();
            std::cin >> s;
            Work_Ans(s);
            std::sort(&ans[1], &ans[n + 1]);
            std::cout << ans[1].tot<< std::endl<< str[ans[1].num]<<std::endl;
            for (int i = 2; i <= n; ++i)
                if (ans[i].tot == ans[i - 1].tot)
                    std::cout << str[ans[i].num]<<std::endl;
                else break;
        }
    }
    

    luogu3808

    #include <bits/stdc++.h>
    
    const int N = 1000000 + 30;
    
    int n;
    int tot;
    std::string s;
    
    struct AC
    {
        int fail, end, vis[28];
    }a[N];
    
    inline void Insert(std::string str)
    {
        int now = 0;
        int len = str.size();
        for (int i = 0; i < len; ++i)
        {
            if (a[now].vis[str[i] - 'a'] == 0)
                a[now].vis[str[i] - 'a'] = ++tot;    
            now = a[now].vis[str[i] - 'a'];
        }
        ++a[now].end;
    }
    
    inline void Work_Fail()
    {
        int now = 0;
        std::queue < int > q;
        for (int i = 0; i < 26; ++i)
        {
            if (a[now].vis[i] != 0)
            {
                a[a[now].vis[i]].fail = 0;
                q.push(a[now].vis[i]);
            }
        }
        while (!q.empty())
        {
            now = q.front();
            q.pop();
            for (int i = 0; i < 26; ++i)
            {
                if (a[now].vis[i] != 0)
                {
                    a[a[now].vis[i]].fail = a[a[now].fail].vis[i];
                    q.push(a[now].vis[i]);
                }
                else
                    a[now].vis[i] = a[a[now].fail].vis[i];
            }    
        }
    }
    
    int Work_Ans(std::string str)
    {
        int now = 0, ans = 0;
        int len = str.size();
        for (int i = 0; i < len; ++i)
        {
            now = a[now].vis[str[i] - 'a'];
            for (int t = now; t != 0 && a[t].end != -1; t = a[t].fail)
            {
                ans += a[t].end;
                a[t].end = -1;
            }
        }
        return ans;
    }
    
    int main() 
    {
        std::cin >> n;
        for (int i = 1; i <= n; ++i)
        {
            std::cin >> s;
            Insert(s);
        }    
        Work_Fail();
        std::cin >> s;
        printf ("%d
    ", Work_Ans(s));
        return 0;
    }
    
  • 相关阅读:
    文本比较算法Ⅴ——回顾贴,对前面几篇文章的回顾与质疑
    键盘监控的实现Ⅱ——容易产生误解的CallNextHookEx函数
    利用WPF建立自适应窗口大小布局的WinForm窗口
    计算机中的颜色XIII——颜色转换的快速计算公式
    键盘监控的实现Ⅲ——按键消息的修改(映射)
    计算机中的颜色XI——从色相值到纯色的快速计算(新的公式)
    Dot Net中InputLanguage对象的使用限制
    计算机中的颜色XII——快速计算纯色的色相值(新的公式)
    关于房产中介网的设计随想
    java笔记:熟练掌握线程技术基础篇之解决资源共享的问题(中)前篇
  • 原文地址:https://www.cnblogs.com/martixx/p/13553618.html
Copyright © 2011-2022 走看看