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;
    }
    
  • 相关阅读:
    轻松背后的N+疲惫——系统日志
    Wcf实现IServiceBehavior拓展机制
    一个迭代小算法,根据指定的个数对下标进行分组
    SqlServer 游标用法
    DataView RowFilter
    Asp.net Repeater 排序
    asp.net 导出Excel
    C# 导出Excel(csv )
    C# 上传图片
    C# 调用外部.exe文件
  • 原文地址:https://www.cnblogs.com/martixx/p/13553618.html
Copyright © 2011-2022 走看看