【问题标题】:Finding a pattern in a matrix in any order? [closed]以任何顺序在矩阵中查找模式? [关闭]
【发布时间】:2016-03-06 22:20:43
【问题描述】:

这是我研究过的一个问题。目标是在二维字母矩阵中找到模式。问题是,即使出现这种模式,我也应该能够找到它

  1. 跨行
  2. 跨列
  3. 沿着

对角线。

设矩阵为

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.

我确信会有一些算法可以强力找出简单二维矩阵中的任何模式。但经过数小时的努力,我无法怀孕。

请建议一种在 C 中解决此问题的方法。我知道使用脚本和基于文本的方法很容易,但我正在寻找一种可以在 C 中实现的算法。

p.s 这不是家庭作业问题或工作分配。我很想知道这就是全部。

【问题讨论】:

  • 首先将您的线性化算法应用于矩阵的转置以获得列匹配(假设输入是行主要的),并且类似于对角线和交叉元素的线性化。完成后概括和浓缩

标签: c algorithm matrix


【解决方案1】:

我尝试将网格存储在char 的二维数组中,因为需要担心的边界条件更少(例如char * 指向不同长度的字符串)。无论如何,这是结果。本例中使用的网格是从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;
}

可能有更有效的算法,例如在网格中搜索单词的第一个字母,然后检查八个方向以查找单词的其余字母(根据网格位置和单词长度过滤掉不可能的方向)。

【讨论】:

  • 我检查了这段代码,这工作得非常好。荣誉
【解决方案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) 来优化如果字符串可以在不超出矩阵边界的情况下进行拟合。

这与洪水填充非常相似,具有额外的约束,即检查必须从初始递归调用沿单一方向进行,而不是螺旋式上升。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    相关资源
    最近更新 更多