这是我所处理的问题。目标是在二维字母矩阵中找到模式。问题是我应该能够找到模式,即使它出现了
对角线。
让矩阵
A B C D
E F G H
I J K L
M N O P
我写了一个C程序,将矩阵作为一个字符指针数组,并使用子字符串(strstr
)来查找模式。我部分成功了。我能够找到在线性化矩阵中连续出现的任何子串。但是我用对角线元素和交叉元素击中了路障。我指的是交叉元素
A
B E
I F C etc.
我确信会有一些算法会在一个简单的2D矩阵中找出任何模式。但经过几个小时的挣扎后,我无法想象它。
请建议一种方法来解决这个问题。我知道使用脚本和基于文本的方法这将是一个简单的方法,但我正在寻找一个可以在C中实现的算法。
p.s这不是家庭工作问题或工作任务。我很想知道这一切。
答案 0 :(得分:2)
(我正在调用这个伪代码 - 以这种方式对矩阵进行分组等是不正确的。)
int match(char** matrix, int width, int height, int x, int y, char *str, int strPos, int strLen, int dx, int dy)
{
if (strPos == strLen)
return 1;
int i = x + dx;
int j = y + dy;
if (i < 0 || i >= width || j < 0 || j >= height || strPos > strLen)
return 0;
/// fix this...
char mc = matrix[x][y];
if (mc != str[strPos])
return 0;
return match(matrix, width, height, i, j, str, strPos + 1, strLen, dx, dy);
}
int matches(char** matrix, int width, int height, char* str, int strLen)
{
for (int i = 0; i < matrixWidth; ++i)
{
for (int j = 0; j < matrixHeight; ++j)
{
if (matrix[i][j] != str[0])
continue;
for (int dx = -1; dx <= 1; ++dx)
{
for (int dy = -1; dy <= 1; ++dy)
{
if (match(matrix, matrixWidth, matrixHeight, i, j, dx, dy))
return 1;
}
}
}
}
return 0;
}
这可能缺少一些边界检查,并且可以通过仅检查方向(dx,dy)来优化,如果字符串可以适合而不超出矩阵边界。
这与洪水填充非常相似,还有一个附加约束,即检查必须从初始递归调用开始,而不是螺旋式上升。
答案 1 :(得分:1)
我尝试将网格存储在char
的二维数组中,因为需要担心的边界条件较少(例如char *
指向不同长度的字符串) 。无论如何,这是结果。在这个例子中使用的网格是&#34;借用&#34;来自Types of Dog Word Search。
#include <stdio.h>
#include <string.h>
static void findword(const char *word, const char *grid, int rows, int cols)
{
int len = strlen(word);
int xdir, ydir, xstart, ystart, xend, yend, xpos, ypos, pos, step, i;
for (xdir = -1; xdir <= 1; xdir++) {
xstart = xdir < 0 ? len - 1 : 0;
xend = xdir > 0 ? cols - len : cols - 1;
if (xend < xstart)
continue;
for (ydir = -1; ydir <= 1; ydir++) {
if (ydir == 0 && xdir == 0)
continue;
ystart = ydir < 0 ? len - 1 : 0;
yend = ydir > 0 ? rows - len : rows -1;
if (yend < ystart)
continue;
for (xpos = xstart; xpos <= xend; xpos++) {
for (ypos = ystart; ypos <= yend; ypos++) {
pos = ypos * cols + xpos;
step = ydir * cols + xdir;
for (i = 0; i < len; i++) {
if (word[i] != grid[pos])
break;
pos += step;
}
if (i == len) {
printf("Found %s at row %d, column %d, dir %s%s\n",
word, ypos + 1, xpos + 1,
ydir < 0 ? "north" : ydir > 0 ? "south" : "",
xdir < 0 ? "west" : xdir > 0 ? "east" : "");
}
}
}
}
}
}
#define GRID_COLS 14
#define GRID_ROWS (sizeof(wordgrid) / sizeof(wordgrid[0]))
static const char wordgrid[][GRID_COLS] = {
"ESULBULLDOGHER",
"EDHISHLSRUDSRE",
"IARELIEWTTORRE",
"RLGTLAEITCORGI",
"EMRDERIISLEPCF",
"HARSCANHHHLEHF",
"CTREDOETOEGBII",
"SIETLPLUHEATHT",
"NAITHXNLAUECUS",
"INRELDEEIBBOAA",
"PNRREOADREHGHM",
"UDEAAERHIAFRUI",
"BRTOBOXERHTSAI",
"LELAMSLRLHUDRL"
};
#define NUM_WORDS (sizeof(words) / sizeof(words[0]))
static const char * const words[] = {
"CHIHUAHUA", "BULLDOG", "TERRIER", "COLLIE", "SHEPHERD", "BOXER",
"HOUND", "BEAGLE", "CORGI", "ROTTWEILER", "PINSCHER", "DALMATIAN",
"SETTER", "MASTIFF"
};
int main(void)
{
int i;
printf("Grid:\n\n");
for (i = 0; i < GRID_ROWS; i++)
printf("%.*s\n", GRID_COLS, wordgrid[i]);
printf("\n");
for (i = 0; i < NUM_WORDS; i++) {
printf("*** Looking for %s ***\n", words[i]);
findword(words[i], &wordgrid[0][0], GRID_ROWS, GRID_COLS);
}
return 0;
}
可能有更高效的算法,例如在网格中搜索单词的第一个字母,然后检查单词剩余字母的八个方向(根据网格位置和字长过滤掉不可能的方向)。