【问题标题】:Searching a word in a given string array在给定的字符串数组中搜索单词
【发布时间】:2013-11-28 02:16:18
【问题描述】:

通过键盘给你一个二维数组作为字符串和一个单词。这个单词 可以以任何方式(要考虑所有 8 个邻居),但您不能使用 匹配时两次相同的字符。返回单词的第一个和最后一个 字符的索引为 (x,y)。如果未找到匹配项,则返回 -1。

这就是问题所在。我在搜索时遇到问题。我试过了:

int x=0,y=0;
            for(int f=0; f<WordinArray.length; f++){
                for(int i=0; i<matrix.length; i++){
                    for(int j=0; j<matrix[0].length; j++){
                        if(matrix[i][j].equals(WordinArray[f])){
                            x=i; y=j;
                            System.out.print("("+x+","+y+")");

                        }
                    }
                }
            }

但是,该代码没有按预期工作。我还能怎么写这个搜索代码?

【问题讨论】:

  • (all 8 neighbors to be considered : 多解释一下
  • 八个可能的方向:水平、垂直和对角线 XY( 0, 1 ), XY( 0, -1 ), XY( 1, 0 ), XY( -1, 0 ) XY( 1 , 1 ), XY( 1, -1 ), XY( -1, 1 ), XY( -1, -1 )
  • 你是说这是一个字母数组,就像一个单词搜索谜题?
  • 这是你的问题吗? uva.onlinejudge.org/…
  • 没错,我需要一个递归。但问题是,我还不知道如何进行递归。因此,我必须编写没有递归的代码。 @JorgeCampos

标签: java arrays search multidimensional-array


【解决方案1】:

参考Sixie's code

假设这是您程序的有效输入/输出?

Size:
4x4
Matrix:
a b c d
e f g h
i j k l
m n o p
Word: afkp
(0,0)(3,3)

我编辑了您的代码,因此它应该适用于此表单的输入(目前区分大小写,但可以通过设置 .toLowerCase() 轻松更改

Scanner k = new Scanner(System.in);
System.out.println("Size: ");
String s = k.nextLine();
s.toUpperCase();

int Xindex = s.indexOf('x');
int x = Integer.parseInt(s.substring(0, Xindex));
int y = Integer.parseInt(s.substring(Xindex + 1));

System.out.println("Matrix:");
char[][] matrix = new char[x][y];

for (int i = 0; i < x; i++) {
    for (int p = 0; p < y; p++) {
        matrix[i][p] = k.next().charAt(0);
    }
}

System.out.print("Word: ");
String word = k.next();

int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;

// looping through the matrix
for (int i = 0; i < x; i++) {
    for (int j = 0; j < y; j++) {
        // when a match is found at the first character of the word
        if (matrix[i][j] == word.charAt(0)) {
            int tempxStart = i;
            int tempyStart = j;
            // calculating all the 8 normals in the x and y direction
            // (the 8 different directions from each cell)
            for (int normalX = -1; normalX <= 1; normalX++) {
                for (int normalY = -1; normalY <= 1; normalY++) {
                    // go in the given direction for the whole length of
                    // the word
                    for (int wordPosition = 0; wordPosition < word
                            .length(); wordPosition++) {
                        // calculate the new (x,y)-position in the
                        // matrix
                        int xPosition = i + normalX * wordPosition;
                        int yPosition = j + normalY * wordPosition;
                        // if the (x,y)-pos is inside the matrix and the
                        // (x,y)-vector normal is not (0,0) since we
                        // dont want to check the same cell over again
                        if (xPosition >= 0 && xPosition < x
                                && yPosition >= 0 && yPosition < y
                                && (normalX != 0 || normalY != 0)) {
                            // if the character in the word is not equal
                            // to the (x,y)-cell break out of the loop
                            if (matrix[xPosition][yPosition] != word
                                    .charAt(wordPosition))
                                break;
                            // if the last character in the word is
                            // equivalent to the (x,y)-cell we have
                            // found a full word-match.
                            else if (matrix[xPosition][yPosition] == word
                                    .charAt(wordPosition)
                                    && wordPosition == word.length() - 1) {
                                xStart = tempxStart;
                                yStart = tempyStart;
                                xEnd = xPosition;
                                yEnd = yPosition;
                            }
                        } else
                            break;
                    }
                }
            }
        }
    }
}
System.out.println("(" + xStart + "," + yStart + ")(" + xEnd + ","
        + yEnd + ")");
k.close();

【讨论】:

  • 程序按照您最初编写的方式运行。我写了blocksAvailable[][] 以了解该位置是否已被控制。 reversedWord 也用于搜索单词的反向。我的意思是,程序必须搜索并找到 ROAD 和 DAOR 的第一个和最后一个索引。此外,程序必须找到可能被赋予横向、水平和垂直的词。
  • @Sixie 添加解决方案
  • 感谢您的帮助!显然,我正在努力。我什至没有想到将矩阵作为字符。
  • @Sixie 没问题。请批准答案,以便其他有类似问题的人也可以使用此代码示例!
  • 您可能需要考虑使用比ijkk1xyxxyy 更清晰的变量名称, x1y1。不可能知道什么变量做了什么,这使得这段代码有点不可维护。通过回答这样的问题,你正在教别人如何编程;这不是一种好的教学方式。
【解决方案2】:

我认为在开始编写代码之前,您需要更仔细地规划您的算法。如果我这样做,我的算法可能看起来像这样。

(1) 遍历数组,寻找单词的第一个字符。

(2) 每次找到第一个字符时,检查所有 8 个邻居,看看是否有第二个字符。

(3) 每次我发现第二个字符与第一个字符相邻时,沿着数组中的字符进行迭代,朝着正确的方向移动,并根据单词检查每个字符。

(4) 如果我匹配了整个单词,则打印出找到匹配的位置并停止。

(5) 如果我已经到达了网格的边缘,或者发现了一个不匹配的字符,那么继续循环的下一次迭代(2)。

确定算法后,请考虑如何将每个步骤转换为代码。

【讨论】:

  • 我按照您的建议研究算法。但这一次问题发生了变化。我无法打印第一个和最后一个字母的索引。
  • 好的,如果你想将你的新代码粘贴到问题中,我会看看我是否能解决你的问题。不要替换旧代码(因为这会改变问题);只需将新代码附加到末尾即可。
【解决方案3】:

如果我理解你的问题是正确的。这是我现在做出的快速回答。

int H = matrix.length;
int W = matrix[0].length;
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;

String word = "WordLookingFor".toLowerCase();

for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
        if (matrix[i][j] == word.charAt(0)) {
            int tempxStart = i;
            int tempyStart = j;
            for (int x = -1; x <= 1; x++) {
                for (int y = -1; y <= 1; y++) {
                    for (int k = 0; k < word.length(); k++) {
                        int xx = i+x*k;
                        int yy = j+y*k;
                        if(xx >= 0 && xx < H && yy >= 0 && yy < W && (x != 0 || y != 0)) {
                            if(matrix[xx][yy] != word.charAt(k))
                                break;
                            else if (matrix[xx][yy] == word.charAt(k) && k == word.length()-1) {
                                xStart = tempxStart;
                                yStart = tempyStart;
                                xEnd = xx;
                                yEnd = yy;
                            }
                        } else
                            break;
                    }
                }
            }
        }
    }
}

我用来检查所有 8 个邻居的一个小技巧是使用两个 for 循环来创建所有进入的方向:

for (int x = -1; x <= 1; x++) {
    for (int y = -1; y <= 1; y++) {
        if(x !=0 || y != 0)
            System.out.println(x + ", " + y);
    }
}

这会创建

-1, -1
-1, 0
-1, 1
0, -1
0, 1
1, -1
1, 0
1, 1

注意:除 0,0 之外的所有值(您不想重新访问同一个单元格)。 其余的代码只是简单地遍历字符矩阵,遍历您要查找的单词的整个长度,直到找到(或者您可能没有找到)完全匹配。

【讨论】:

    【解决方案4】:

    这次的问题是如何打印单词的第一个和最后一个 信的索引。我尝试了各种方法,例如在每个单词后打印 被搜查了。但是,所有这些都不起作用。我要炸了。

    int[] values = new int[2];
                    for(int i=0; i<matrix.length; i++){
                        for(int j=0; j<matrix[0].length; j++){
    
                            if(Character.toString(word.charAt(0)).equals(matrix[i][j]) == true || Character.toString(ReversedWord.charAt(0)).equals(matrix[i][j]) == true ){
                                System.out.print("("+ i + "," +j+")");
                                //First letter is found.Continue.
                            for(int p=1; p<word.length(); p++){
    
                            try{
                                for (int S = -1; S <= 1; S++) {
                                    for (int SS = -1; SS <= 1; SS++) {
                                        if(S !=0 || SS != 0)
                                            if(matrix[i+S][j+SS].equals(Character.toString(word.charAt(p))) && blocksAvailable[i+S][j+SS] == true || 
                                                matrix[i+S][j+SS].equals(Character.toString(ReversedWord.charAt(p))) && blocksAvailable[i+S][j+SS] == true) {
                                                    values[0] = i+S;
                                                    values[1] = j+SS;
                                                    blocksAvailable[i+S][j+SS] = false;
    
    
                                            }
                                    }
                                }
                            }catch (ArrayIndexOutOfBoundsException e) {}
    

    【讨论】:

    • 我在上面的回答中解决了你的问题。只需在代码末尾打印变量 xStart、yStart、xEnd、yEnd。那是与单词开头和结尾索引对应的变量。请告诉我包括矩阵在内的整个代码。
    • @ExceptionalException 实际上,您的代码帮助很大,但我无法全部理解。这是我的代码,My Code
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 2011-12-27
    • 2019-02-12
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    相关资源
    最近更新 更多