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; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/