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\n", ans);
    }

    return 0;
}

  

posted @ 2016-01-12 11:20  Running_Time  阅读(223)  评论(0编辑  收藏  举报