Uva11019——二维字符串匹配
2013-03-09 16:46
831 查看
题意:给出两个字符串矩阵A1,A2判断A2在A1中出现多少次。
思路还是很明确的,而且很容易想到:用A2的每一行字符构造ac自动机,然后去匹配A1的每一行字符,每一次匹配到了单词节点,则在A1中将该字符标记(可以用一个二维数组保存标记),一旦匹配到了A2的最后一行的单词节点,则回头去检测在A1中相同列的连续的若干行中的字符的标记是否满足要求。而且由于ac自动机中每一个单词的长度都是一样的,所以不需要考虑某个单词节点的失配指针路径上是否有单词节点(肯定没有)。
还有一个要处理的问题:A2当中可能出现的相同的行,那么对应构造的ac自动机中前面行的单词节点会被后面的覆盖,因此在匹配A1的每一行时,若碰到单词节点,标记的肯定是与之匹配的A2种行号最大的那一行,那么在返回检测的时候,就有可能误判。我的做法是有数组trans[i]表示A2中与行i相同的行号最大的那一行的行数,在向ac自动机中插入字符串标记单词节点的时候,注意判断一下该节点是否已经是单词节点,如果是更新一下trans数组。
思路还是很明确的,而且很容易想到:用A2的每一行字符构造ac自动机,然后去匹配A1的每一行字符,每一次匹配到了单词节点,则在A1中将该字符标记(可以用一个二维数组保存标记),一旦匹配到了A2的最后一行的单词节点,则回头去检测在A1中相同列的连续的若干行中的字符的标记是否满足要求。而且由于ac自动机中每一个单词的长度都是一样的,所以不需要考虑某个单词节点的失配指针路径上是否有单词节点(肯定没有)。
还有一个要处理的问题:A2当中可能出现的相同的行,那么对应构造的ac自动机中前面行的单词节点会被后面的覆盖,因此在匹配A1的每一行时,若碰到单词节点,标记的肯定是与之匹配的A2种行号最大的那一行,那么在返回检测的时候,就有可能误判。我的做法是有数组trans[i]表示A2中与行i相同的行号最大的那一行的行数,在向ac自动机中插入字符串标记单词节点的时候,注意判断一下该节点是否已经是单词节点,如果是更新一下trans数组。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int maxn = 10000 + 50; const int sigma_size = 128; int mark[1005][1005], m, n, x, y, trans[1000], res; char str[1005][1005]; struct ac_machine { int ch[maxn][sigma_size]; int val[maxn]; int f[maxn]; int sz; void init() { sz = 1; memset(ch, 0, sizeof(ch)); memset(val, 0, sizeof(val)); memset(f, 0, sizeof(f)); } int idx(char c) { return c - '\0'; } void insert(char * s, int v) { int u = 0; for(int i = 0; s[i]; ++i) { int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = sz++; u = ch[u][c]; } if(val[u] != 0) { for(int i = 1; i < v; ++i) if(trans[i] == val[u]) trans[i] = v; } val[u] = v; } void getFail() { queue<int> q; f[0] = 0; for(int i = 0; i < sigma_size; ++i) { if(ch[0][i]) { q.push(ch[0][i]); f[ch[0][i]] = 0; } else ch[0][i] = 0; } while(!q.empty()) { int u = q.front(); q.pop(); for(int i = 0; i < sigma_size; ++i) { int v = ch[u][i]; if(v) { q.push(v); int p = f[u]; while(p && ch[p][i] == 0) p = f[p]; f[v] = ch[p][i]; } else ch[u][i] = ch[f[u]][i]; } } } void find() { for(int a = 0; a < m; ++a) { int u = 0; for(int i = 0; i < n; ++i) { int c = idx(str[a][i]); u = ch[u][c]; if(val[u]) { mark[a][i] = val[u]; if(val[u] == x && a >= x - 1) { //cout << a << " " << i << "\n"; bool sign = true; for(int j = a, k = x; k > 0; --k, --j) if(mark[j][i] != trans[k]) { sign = false; break; } if(sign) res++; } } } } } }ac; int main() { freopen("in.txt", "r", stdin); int t; scanf("%d", &t); while(t--) { res = 0; ac.init(); for(int i = 1; i <= 100; ++i) trans[i] = i; memset(mark, 0, sizeof(mark)); scanf("%d %d", &m, &n); for(int i = 0; i < m; ++i) scanf("%s", str[i]); scanf("%d %d", &x, &y); for(int i = 0; i < x; ++i) { char tempstr[104]; scanf("%s", tempstr); ac.insert(tempstr, i + 1); } ac.getFail(); ac.find(); printf("%d\n", res); } return 0; } /* 2 1 1 x 1 1 y 3 3 abc bcd cde 2 2 bc cd 0 2 */
相关文章推荐
- Uva 11019 Matrix Matcher(二维字符串匹配)
- 【Uva11019】Matrix Matcher【AC自动机】【二维字符串匹配】
- UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
- UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
- UVA 11019(Matrix Matcher-vector从迭代器中取值,AC自动机匹配字符矩阵)
- uva11019 - Matrix Matcher 二维矩阵匹配 AC自动机
- UVa 489 Hangman Judge (模拟&字符串匹配)
- UVA - 11019 Matrix Matcher (AC自动机(二维匹配) + dp)
- uva 11019 Matrix Matcher (ac自动机二维匹配)
- AC自动机(二维) UVA 11019 Matrix Matcher
- UVa 11019 Matrix Matcher 字符矩阵出现次数
- UVA 11019 Matrix Matcher(二维矩阵匹配ac自动机)
- uva:10340 - All in All(字符串匹配)
- UVa 401 Palindromes (字符串匹配)
- HDU 1606(POJ 1598 UVA 409) Excuses, Excuses!(字符串匹配处理)
- UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串
- uva 11081 Strings 字符串匹配
- 【字符串匹配】UVALive 4670 模板题
- UVA-1588-Kickdown:简单字符串匹配
- UVa 409 Excuses, Excuses! (字符串匹配)