我想创建一个程序来搜索文本中的子文本。
例如,我有这样的文字:ab cd eabbdfeg
在那篇文章中我想找到: cd
但我想使用这个算法:
start = 1
end = string length of the text
middle = (start + end) / 2
if (pattern < text[middle]) end = mid - 1;
if (pattern > text[middle]) start = mid + 1;
...and continue until the pattern is found in the text
所以,我已经有一个简单的程序完全没有任何问题,但上面没有那个算法,所以现在我只想在我的程序中实现上面的算法,我已经尝试了很多方法,但我的程序赢了&#39;在添加该算法后,无论如何都显示任何内容......
这是我拥有并运作的代码:
void search(char *pat, char *txt)
{
int M = strlen(pat);
int N = strlen(txt);
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
{
if (txt[i+j] != pat[j])
break;
}
if (j == M)
{
printf("Pattern found at index %d \n", i);
}
}
}
这是上面的代码与算法的实现:
int _tmain(int argc, _TCHAR* argv[])
{
char t[32];
cout << "Please enter your text (t):";
cin >> t;
char p[32];
cout << "Please enter the pattern (p) you wish to look for in that text (t):";
cin >> p;
int start, end = 0;
double middle = 0;
start = 1;
end = strlen(t);
while (start <= end)
{
int M = strlen(p);
int N = strlen(t);
middle = std::ceil((start + end) / 2.0);
int mid = (int)middle;
for (int i = mid; i <= M; i++)
{
int j;
for (j = 0; j < M; j++)
{
if (t[mid] != p[j]) break;
if (p[j] < t[mid]) { end = mid - 1; }
else if (p[j] > t[mid]) { start = mid + 1; }
}
if (j == M)
{
printf("Pattern found at index %d \n", i);
}
}
}
if (start > end) cout << "Search has ended: pattern p does not occur in the text." << endl;
return 0;
}
答案 0 :(得分:0)
您的算法仍然是二进制搜索。您将阵列拆分为两个分区,然后根据字母值选择一个分区。
分区搜索的要求是拥有有序集合。
让我们用你的例子。
0 1 2 3 4 5 6 7 8 9 10 11
+---+---+---+---+---+---+---+---+---+---+---+---+
| a | b | c | d | e | a | b | b | d | f | e | g |
+---+---+---+---+---+---+---+---+---+---+---+---+
如果您选择索引5处的中点,则会生成字母a
。由于您首先搜索字母c
,然后d
,因此算法会说字母c
必须位于分区6..11中。这是你问题的基础。
算法找不到cd
,因为分区6..11中没有c
。
该算法假设数组已排序,对于任何给定索引,将有一个分区包含小于array [index]的值,一个分区包含大于array [index]的值。
您的以下代码证明了这一假设:
if (p[j] < t[mid]) { end = mid - 1; }
else if (p[j] > t[mid]) { start = mid + 1; }
无论您如何命名算法,如果它假定数组有序(例如p[j] < t[mid]
),则必须订购数组。
您的数据没有排序,因此您的算法不符合假设,因此算法失败。
修改1:
如果您确实必须使用分区算法,则需要构建一组分区。
例如,一个分区从索引0开始并继续直到array [i]&gt; array [i + 1],这最终在索引4处。另一个分区是5..11。
(顺便说一句,通过确定分区,您使用的操作多于线性搜索。)
此时,您如何知道选择哪个分区?
你没有。您要搜索的字母c
位于第一个分区中的a
和e
之间;和第二个分区中的a
到g
。选择一个分区。如果在分区中找不到,则必须搜索其他分区。
通过在任一分区上执行二进制搜索,您使用的操作多于线性搜索。