Uva11019 Matrix Matcher-AC自动机二维匹配

一看题冒出各种奇奇怪怪不可做的想法

其实做法也很简单

把每行作为模式串插入AC自动机

再拿小矩阵每行去匹配

在匹配成功之后需要搞点事情

匹配成功后给对应的左上角的计数器加一

最后统计一遍即可

代码里有一些特别奇怪的东西,比如拿邻接表存相同的行什么的(要不会MLE)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;

const int MAXN = 1002, MAXX = 102, MAXNnode = 1000002;

struct Node{
    int tag, fail, nxt[26];
    inline void init(){tag = fail = 0; memset(nxt, 0, sizeof(nxt));}
}t[MAXNnode];
int T, n, m, n2, m2, ptr, Root;
int cnt[MAXN][MAXN], head[MAXX];
char txt[MAXN][MAXN], str[MAXX][MAXX];
queue<int> q;

inline void Insert(int No) {
    int cur = Root;
    for(int i = 1; i <= m2; ++i) {
        register int x = str[No][i] - 'a';
        if(!t[cur].nxt[x]) {
            t[cur].nxt[x] = ++ptr;
            t[ptr].init();
        }
        cur = t[cur].nxt[x];
    }
    if(t[cur].tag) head[No] = t[cur].tag;
    t[cur].tag = No;
    return;
}
inline void getfail() {
    t[Root].fail = 0;
    for(int i = 0; i < 26; ++i) 
        if(t[Root].nxt[i]) {
            t[t[Root].nxt[i]].fail = Root;
            q.push(t[Root].nxt[i]);
        } else t[Root].nxt[i] = Root;
    while(!q.empty()) {
        int cur = q.front(); q.pop();
        for(int i = 0; i < 26; ++i) {
            register int son = t[cur].nxt[i];
            if(!son) {
                t[cur].nxt[i] = t[t[cur].fail].nxt[i];
                continue;
            }
            t[son].fail = t[t[cur].fail].nxt[i];
            if(t[t[son].fail].tag) t[son].tag = t[t[son].fail].tag;
            q.push(son);
        }
    }
    return;
}
inline void update(int x, int y, int z) {
    if(x >= z) ++cnt[x - z + 1][y - m2 + 1];
    while(head[z]) {
        z = head[z];
        if(x >= z) ++cnt[x - z + 1][y - m2 + 1];
    }
    return;
}
inline void acfind() {
    int cur = Root;
    for(int i = 1; i <= n; ++i) {
        cur = Root;
        for(int j = 1; j <= m; ++j) {
            cur = t[cur].nxt[txt[i][j] - 'a'];
            if(t[cur].tag) 
                update(i, j, t[cur].tag);
        }
    }
    return;
}
inline void resetall() {
    ptr = 0;
    memset(t + Root, 0, sizeof(Node));
    memset(head, 0, sizeof(head));
    for(int i = 0; i <= n; ++i) 
        for(int j = 0; j <= m; ++j) 
            cnt[i][j] = 0;
    return;
}
inline int rd() {
    register int x = 0;
    register char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)) {
        x = x * 10 + (c ^ 48);
        c = getchar();
    }
    return x;
}

int main() {
    T = rd();
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%s", txt[i] + 1);
        scanf("%d%d", &n2, &m2);
        for(int i = 1; i <= n2; ++i) {
            scanf("%s", str[i] + 1);
            Insert(i);
        }
        getfail();
        acfind();
        int ans = 0;
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m; ++j) {
                if(cnt[i][j] >= n2) ++ans;
            }
        }
        printf("%d\n", ans);
        resetall();
    }
    return 0;
}

 

posted @ 2018-07-15 21:16  EvalonXing  阅读(183)  评论(0编辑  收藏  举报