[英]Word search algorithm segmentation fault
i've been working on word search algorithm for quite long I think i made it good and decided to test limits. 我一直在研究单词搜索算法很长时间,我认为我做得很好,并决定测试极限。 I've created program which makes file as big as I want to. 我已经创建了程序,该程序可以使文件尽可能的大。 So i made a matrix 10000 * 10000 (10000000 letters) and really long word from top left corner to bottom right corner. 所以我做了一个矩阵10000 * 10000(10000000个字母),并且从左上角到右下角都有很长的单词。 Thing is that it works with 4000 * 4000 matrix but then it gets bigger it just crashes. 事实是,它可以与4000 * 4000矩阵一起使用,但随后变得更大,它崩溃了。 I tried to comment all other checkings for possible location and left the right one and it works perfectly even with 10000 * 10000 matrix but as soon as I add other checks it stops and I have no idea why. 我试图注释所有其他检查以查找可能的位置,并在右边进行左对齐,即使使用10000 * 10000矩阵,它也可以正常工作,但是一旦添加其他检查,它就会停止并且不知道为什么。 Any suggestions? 有什么建议么?
My code: 我的代码:
#include <iostream> //Might Be:
#include <string> // <----->
#include <fstream> // /-\ (1)/\ /\(3)
#include <new> // | \ /
#include <cstdlib> // | \ /
// | \ /
// | \ /
// | \ /
// \_/ (2)\/ \/(4)
//
using namespace std;
//Loop[4] //Loop[5]
int * Possibles(int Widht, int Height, int Poz, int Poz1, int Leng, int * Possible)
{
if(Poz1 < Widht - Leng + 1) // To right
{
Possible[0] = 1;
}
if(Poz1 >= Leng - 1) // To left
{
Possible[1] = 1;
}
if(Poz <= Height - Leng) // From top to bottom
{
Possible[2] = 1;
}
if(Poz >= Leng) // From bottom to top
{
Possible[3] = 1;
}
if(Poz + Leng <= Height && Poz1 + Leng <= Widht) //(2)
{
Possible[4] = 1;
}
if(Poz + Leng <= Height && Poz1 - Leng + 1 >= 0) //(4)
{
Possible[5] = 1;
}
if(Poz - Leng + 1 >= 0 && Poz1 - Leng + 1 >= 0) //(1)
{
Possible[6] = 1;
}
if(Poz - Leng + 1 >= 0 && Poz1 + Leng <= Widht) //(3)
{
Possible[7] = 1;
}
return Possible;
}
int * Zero(int * Possible)
{
Possible[0] = 0;
Possible[1] = 0;
Possible[2] = 0;
Possible[3] = 0;
Possible[4] = 0;
Possible[5] = 0;
Possible[6] = 0;
Possible[7] = 0;
return Possible;
}
string Next(string * NewMatrix, int Height, int Widht)
{
return NewMatrix[Height].substr(Widht, 1);
}
bool Find(string Word, int Poz, int Poz1, int Look, string Have, string * Matrix, int * Possible, int Backup, int Backup1)
{
if(Have == Word)
{
return true;
return Possible;
}
string NewLet = Word.substr(Look, 1);
if(Possible[0] == 1)
{
if(NewLet == Next(Matrix, Poz, Poz1 + 1))
{
Have += NewLet;
return Find(Word, Poz, Poz1 + 1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[0] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[1] == 1)
{
if(NewLet == Next(Matrix, Poz, Poz1 - 1))
{
Have += NewLet;
return Find(Word, Poz, Poz1 - 1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[1] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[2] == 1)
{
if(NewLet == Next(Matrix, Poz + 1, Poz1))
{
Have += NewLet;
return Find(Word, Poz + 1, Poz1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[2] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[3] == 1)
{
if(NewLet == Next(Matrix, Poz - 1, Poz1))
{
Have += NewLet;
return Find(Word, Poz - 1, Poz1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[3] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[4] == 1)
{
if(NewLet == Next(Matrix, Poz + 1, Poz1 + 1))
{
Have += NewLet;
return Find(Word, Poz + 1, Poz1 + 1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[4] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[5] == 1)
{
if(NewLet == Next(Matrix, Poz + 1, Poz1 - 1))
{
Have += NewLet;
return Find(Word, Poz + 1, Poz1 - 1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[5] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[6] == 1)
{
if(NewLet == Next(Matrix, Poz - 1, Poz1 - 1))
{
Have += NewLet;
return Find(Word, Poz - 1, Poz1 - 1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[6] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
if(Possible[7] == 1)
{
if(NewLet == Next(Matrix, Poz - 1, Poz1 + 1))
{
Have += NewLet;
return Find(Word, Poz - 1, Poz1 + 1, Look + 1, Have, Matrix, Possible, Backup, Backup1);
}
else
{
Possible[7] = 0;
Have = Word.substr(0, 1);
return Find(Word, Backup, Backup1, 1, Have, Matrix, Possible, Backup, Backup1);
}
}
return false;
}
string Diro(int * Possible)
{
string Dir;
bool Next = true;
if(Possible[0] == 1 && Next == true)
{
Dir = " From right to left";
Next = false;
}
if(Possible[1] == 1 && Next == true)
{
Dir = " From left to right";
Next = false;
}
if(Possible[2] == 1 && Next == true)
{
Dir = " From top to bottom";
Next = false;
}
if(Possible[3] == 1 && Next == true)
{
Dir = " From bottom to top";
Next = false;
}
if(Possible[4] == 1 && Next == true)
{
Dir = " ";
Next = false;
}
if(Possible[5] == 1 && Next == true)
{
Dir = " ";
Next = false;
}
if(Possible[6] == 1 && Next == true)
{
Dir = " ";
Next = false;
}
if(Possible[7] == 1 && Next == true)
{
Dir = " ";
Next = false;
}
return Dir;
}
int main()
{
int Height = 0, Widht = 0, Numb = 0;
int Loop[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
int * Possible = new int[8];
string Dir, Search, Tempo, Temp;
ifstream Data("C:/Users/Magician/AppData/Local/VirtualStore/Program Files (x86)/CodeBlocks/MakeMaze/Files/Maze.txt");
Data >> Widht >> Height;
string * NewMatrix = new string[Height];
while(Loop[7] < Height)
{
Tempo = "";
Loop[8] = 0;
while(Loop[8] < Widht)
{
Data >> Temp;
Tempo += Temp;
Loop[8]++;
}
NewMatrix[Loop[7]] = Tempo;
Loop[7]++;
}
Data >> Numb;
string * Words = new string[Numb];
while(Loop[2] < Numb)
{
Data >> Words[Loop[2]];
Loop[2]++;
}
Data.close();
while(Loop[3] < Numb)
{
Search = Words[Loop[3]].substr(0, 1);
Loop[4] = 0;
while(Loop[4] < Height)
{
Loop[5] = 0;
while(Loop[5] < Widht)
{
if(NewMatrix[Loop[4]].substr(Loop[5], 1) == Search)
{
Zero(Possible);
Possibles(Widht, Height, Loop[4], Loop[5], Words[Loop[3]].size(), Possible);
if(Find(Words[Loop[3]], Loop[4], Loop[5], 1, Search, NewMatrix, Possible, Loop[4], Loop[5]))
{
cout << Words[Loop[3]] << " At: " << Loop[4] + 1 << " collumn, symbol " << Loop[5] + 1 << " " << Diro(Possible) << endl;
Loop[5] = Widht;
Loop[4] = Height;
}
}
Loop[5]++;
}
Loop[4]++;
}
Loop[3]++;
}
delete [] Possible;
delete [] Words;
delete [] NewMatrix;
return 0;
}
If you didn't understood what I wrote before: when I comment every if(Possible[] == ) except for if(Possible[5] == 1) in function Find() algorithm works then all allowed it doesn't. 如果您不了解我之前写的内容:当我对函数if(Possible [5] == 1)中的所有if(Possible [] == 1)进行注释时,所有允许的注释都无效。 I've tried with 100 * 100 matrix with a lot of words to find and everything's ok. 我已经尝试使用100 * 100矩阵来查找很多单词,并且一切正常。
One condition in Possibles
is incorrect: Possibles
一个条件不正确:
/* INCORRECT: Should be [ Poz >= Leng - 1 ] */ if(Poz >= Leng) // From bottom to top { Possible[3] = 1; }
But this one is only a logical error and should not cause segmentation faults. 但是,这只是一个逻辑错误,不应引起分段错误。
It looks like you have encountered a stack overflow. 看来您遇到了堆栈溢出。
Let's do simple calculation. 让我们做简单的计算。 For 10000 * 10000 matrix and word length of 10000, if you start calling Find()
at the top left of the matrix, then three directions are possible. 对于10000 * 10000矩阵和10000字长,如果您开始在矩阵的左上方调用Find()
,则可能会出现三个方向。 In worst case, Find()
will traverse about 10000*3 elements. 在最坏的情况下, Find()
将遍历大约10000 * 3个元素。 Note in Func()
there are 3 string instances (sizeof(string) == 24 in 32bit VC2013), plus various integers. 请注意,在Func()
有3个字符串实例(在32位VC2013中为sizeof(string)== 24),以及各种整数。 The size of a single frame could easily exceed 100 bytes. 单帧的大小很容易超过100个字节。 Since you are using recursive calls, this could lead to a stack usage of at least 10000 * 3 * 100 = 3000000bytes = approx. 由于您正在使用递归调用,因此这可能导致至少10000 * 3 * 100 = 3000000bytes =大约使用堆栈。 3M. 3M。
This number is not very large, but enough for a stack overflow since Windows has a default stack size of 1M. 这个数字不是很大,但是足以使堆栈溢出,因为Windows的默认堆栈大小为1M。 ( http://msdn.microsoft.com/en-us/library/8cxs58a6.aspx ) ( http://msdn.microsoft.com/en-us/library/8cxs58a6.aspx )
Advice for improvements 改进建议
This is my used pattern to solve this kinds of matrix traversal
problems. 这是我用来解决此类matrix traversal
问题的模式。
First, define an constant array to hold offsets for movements ( Moore neighborhood ): 首先,定义一个常数数组来保存运动的偏移量( 摩尔邻域 ):
const int delta[8][2] = {
{ 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 },
{ -1, 0 }, { -1, -1 }, { 0, -1 }, { 1, -1 }
};
Second, use a single for
to check for all directions: 其次,使用单一for
检查各个方向:
int initial_x = .., initial_y = ..;
for (int dir = 0; dir < 8; dir++) {
for (int count = 0; count < WORD_LENGTH; count++) {
int current_x = initial_x + delta[dir][0] * count;
int current_y = initial_y + delta[dir][1] * count;
if (IS_INVALID(current_x, current_y)) {
break;
}
}
}
Last, insert various code and flags to complete the program. 最后,插入各种代码和标志以完成程序。
Another hint: you can use char
type to get and compare a single character in a string (Use word[idx]
to get idx
th character of word
). 另一个提示:您可以使用char
类型来获取和比较字符串中的单个字符(使用word[idx]
获得idx
第word
个字符)。 This could be substantially faster than using substr
. 这可能比使用substr
快得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.