以任何顺序在矩阵中查找模式?

时间:2015-12-02 15:38:26

标签: c algorithm matrix

这是我所处理的问题。目标是在二维字母矩阵中找到模式。问题是我应该能够找到模式,即使它出现了

  1. 跨行
  2. 跨列
  3. 沿着
  4. 对角线。

    让矩阵

    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这不是家庭工作问题或工作任务。我很想知道这一切。

2 个答案:

答案 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;
}

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