使用定义的算法在文本中搜索子文本

时间:2015-02-16 20:06:09

标签: c++ search

我想创建一个程序来搜索文本中的子文本。

例如,我有这样的文字: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;
}

1 个答案:

答案 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位于第一个分区中的ae之间;和第二个分区中的ag。选择一个分区。如果在分区中找不到,则必须搜索其他分区。

通过在任一分区上执行二进制搜索,您使用的操作多于线性搜索。