• AC自动机(二维) UVA 11019 Matrix Matcher


    题目传送门

    题意:训练指南P218

    分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e3 + 5;
    const int NODE = 1e4 + 5;
    const int SIZE = 26;
    char mat1[N][N], mat2[105][105];
    int cnt[N][N];
    int n, m, x, y;
    struct AC   {
        int ch[NODE][SIZE], val[NODE], sz;
        int fail[NODE], last[NODE];
        vector<int> rows[NODE];
        void clear(void)    {
            memset (ch[0], 0, sizeof (ch[0]));
            sz = 1;
            for (int i=0; i<NODE; ++i)  rows[i].clear ();
        }
        int idx(char c) {
            return c - 'a';
        }
        void insert(char *P, int v)    {
            int u = 0;
            for (int c, i=0; P[i]; ++i)    {
                c = idx (P[i]);
                if (!ch[u][c])  {
                    memset (ch[sz], 0, sizeof (ch[sz]));
                    val[sz] = 0;
                    ch[u][c] = sz++;
                }
                u = ch[u][c];
            }
            val[u] = v;
            rows[u].push_back (v);
        }
        void build(void)    {
            queue<int> que; fail[0] = 0;
            int u;
            for (int c=0; c<SIZE; ++c)  {
                u = ch[0][c];
                if (u)  {fail[u] = 0;    que.push (u);}
            }
            while (!que.empty ())   {
                int r = que.front ();   que.pop ();
                for (int c=0; c<SIZE; ++c)  {
                    int &u = ch[r][c];
                    if (!u) {
                        u = ch[fail[r]][c];
                        continue;
                    }
                    que.push (u);
                    int v = fail[r];
                    while (v && !ch[v][c])    v = fail[v];  //
                    fail[u] = ch[v][c];
                    last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
                }
            }
        }
        void query(int row) {
            int u = 0;
            for (int c, i=0; mat1[row][i]; ++i)    {
                c = idx (mat1[row][i]);
                u = ch[u][c];
                if (i - y + 1 < 0)  continue;
                if (val[u]) print (row, i - y + 1, u);
                else if (last[u])   print (row, i - y + 1, last[u]);
            }
        }
        void print(int r, int c, int u) {
            if (u)  {
                for (int i=0; i<rows[u].size (); ++i)   {
                    int tr = rows[u][i];
                    if (r - tr + 1 >= 1) {
                        cnt[r-tr+1][c]++;
                    }
                }
                print (r, c, last[u]);
            }
        }
    }ac;
    
    int main(void)  {
        int T;  scanf ("%d", &T);
        while (T--) {
            scanf ("%d%d", &n, &m);
            for (int i=1; i<=n; ++i)    {
                scanf ("%s", &mat1[i]);
            }
            ac.clear ();
            scanf ("%d%d", &x, &y);
            for (int i=1; i<=x; ++i)    {
                scanf ("%s", &mat2[i]);
                ac.insert (mat2[i], i);
            }
            ac.build ();
            memset (cnt, 0, sizeof (cnt));
            for (int i=1; i<=n; ++i)    {
                ac.query (i);
            }
            int ans = 0;
            for (int i=1; i<=n-x+1; ++i) {
                for (int j=0; j<=m-y; ++j) {
                    if (cnt[i][j] == x) ans++;
                }
            }
            printf ("%d
    ", ans);
        }
    
        return 0;
    }
    

      

    编译人生,运行世界!
  • 相关阅读:
    Linux进程管理
    GitHub
    MySQL存储过程
    MySQL自定义函数
    MySQL运算符和内置函数
    js类型检测
    防止SQL注入的方法
    PDO数据库抽象层
    PHP操作MySQL的常用函数
    第二周
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5123758.html
Copyright © 2020-2023  润新知