几个用C++写的字符串搜索代码

本文介绍了三种不同的字符串搜索算法:朴素的字符串搜索算法、受Rabin-Karp启发的改进算法及KMP算法,并提供了详细的代码实现。

1.关于本文

本文中所有的代码都为实现一个目标,即:

写一个函数:从字符串s中找到字符串a第一次出现的位置,不存在则返回-1

2.方法1:朴素的字符串搜索算法

用一个循环来找出所有有效位移

#include<iostream>
#include<string>

using namespace std;

//函数:找出字符串s中第一次出现字符串a的位置(朴素算法)
int IndexOf_01(string s,string a)
{
    bool isMatch;
    for(int i = 0; i <= s.length() - a.length(); i++)
    {
        isMatch = true;
        for(int j = 0; j < a.length(); j++)
        {
            if(s[i + j] != a[j])
            {
                isMatch = false;
                break;
            }
        }

        if(isMatch)
        {
            return i;
        }
    }

    return -1;
}

int main()
{
    string s = "the quick brown fox jumped over the lazy dogs";

    cout << s << endl;
    cout << "index of \"the\": " << IndexOf_01(s, "the") << endl;
    cout << "index of \"quick\": " << IndexOf_01(s, "quick") << endl;
    cout << "index of \"dogs\": " << IndexOf_01(s, "dogs") << endl;
    cout << "index of \"cats\": " << IndexOf_01(s, "cats") << endl;

    return 0;
}

 

152221_VACB_1425762.png

3.方法2

本方法受到了 Rabin-Karp 启发,相当于对原算法做了如下修改

窗口长度:m=a.length(),第一次匹配规则:t=t[0]+t[1]+...+t[t.length()-1],模p=max

对于字符串s的每一个长度为m的子串,如果该子串所有字符的ASCII码和与目标字符串相同,则逐个比对该子串与目标字符串是否相同,否则跳过。若子串与目标字符串相同,则认为匹配,否则继续向后搜索。

#include<iostream>
#include<string>

using namespace std;

//函数:找出字符串s中第一次出现字符串a的位置(受到Rabin-Karp算法启发)
int IndexOf_02(string s,string a)
{
    //s的长度应大于a的长度
    if(s.length() < a.length())
    {
        return -1;
    }

    //计算第一组数字和
    int target = 0, current = 0;
    for(int i = 0; i < a.length(); i++)
    {
        target += a[i];
        current += s[i];
    }

    //开始匹配
    bool isMatch;
    for(int i = 0; i <= s.length() - a.length(); )
    {
        //如果所有字符的数字和相同,则进一步比较
        if(current == target)
        {
            isMatch = true;
            for(int j = 0; j < a.length(); j++)
            {
                if(s[i + j] != a[j])
                {
                    isMatch = false;
                    break;
                }
            }

            if(isMatch)
            {
                return i;
            }
        }

        //计算下一组字符的数字和
        current -= s[i];
        current += s[i++ + a.length()];
    }

    return -1;
}

int main()
{
    string s = "the quick brown fox jumped over the lazy dogs";

    cout << s << endl;
    cout << "index of \"the\": " << IndexOf_02(s, "the") << endl;
    cout << "index of \"quick\": " << IndexOf_02(s, "quick") << endl;
    cout << "index of \"dogs\": " << IndexOf_02(s, "dogs") << endl;
    cout << "index of \"cats\": " << IndexOf_02(s, "cats") << endl;

    return 0;
}

152142_Q2zm_1425762.png

4.Knuth-Morris-Pratt(KMP)算法

KMP算法,函数ComputePrefix用于计算辅助数组

#include<iostream>
#include<string>

using namespace std;

//计算前缀
int* ComputePrefix(string a)
{
    int *array = new int[a.length() + 1];

    int x = 0;
    array[0] = 0;
    for(int i = 1; i < a.length(); i++)
    {
        if(a[i] == a[x])
        {
            array[i] = array[i - 1] + 1;
            x++;
        }
        else
        {
            array[i] = 0;
            x = 0;
        }
    }

    return array;
}

//函数:找出字符串s中第一次出现字符串a的位置(KMP算法)
int IndexOf_KMP(string s, string a)
{
    //计算前缀
    int *perfix = new int[a.length()];
    perfix = ComputePrefix(a);

    //判断a在s中第一次出现的位置
    int x = 0, y = 0;
    while(x < s.length())
    {
        if(s[x + y] == a[y])
        {
            y++;
            if(y == a.length())
            {
                return x;
            }
        }
        else
        {
            if(y == 0)
            {
                x++;
            }
            else
            {
                x += (y - perfix[y - 1]);
            }
            y = 0;
        }
    }

    return -1;
}

int main()
{
    string tests = "ababaabababcabab";
    cout << tests << endl;

    string testa0 = "ababa";
    cout << testa0 << ": " << IndexOf_KMP(tests, testa0) << endl;

    string testa1 = "ababc";
    cout << testa1 << ": "  << IndexOf_KMP(tests, testa1) << endl;

    string testa2 = "cabab";
    cout << testa2 << ": " << IndexOf_KMP(tests, testa2) << endl;

    string testa3 = "aaaaa";
    cout << testa3 << ": " << IndexOf_KMP(tests, testa3) << endl;

    return 0;
}

152928_hiej_1425762.png

转载于:https://my.oschina.net/Tsybius2014/blog/272355

### C++实现字符串反转的代码示例 在C++中,可以使用多种方法来实现字符串反转。以下是几种常见的实现方式: #### 方法一:使用循环交换字符 通过遍历字符串的一半长度,并交换首尾字符,可以实现字符串的反转。这种方法适用于C风格字符串或`std::string`类型。 ```cpp #include <iostream> #include <cstring> // 包含 strlen 函数 void reverse(char *str) { if (str) { int len = strlen(str); // 获取字符串长度 char temp; for (int i = 0; i < len / 2; ++i) { // 遍历字符串的一半 temp = str[i]; // 交换首尾字符 str[i] = str[len - i - 1]; str[len - i - 1] = temp; } } } int main() { char str[] = "Hello, World!"; reverse(str); std::cout << str << std::endl; // 输出: !dlroW ,olleH return 0; } ``` 此代码展示了如何通过循环交换字符来反转C风格字符串[^1]。 #### 方法二:使用指针操作 通过定义两个指针分别指向字符串的起始位置和结束位置,并逐步向中间靠拢交换字符,可以实现字符串反转。 ```cpp #include <iostream> #include <cstring> // 包含 strlen 函数 void revstring(char *test) { int length = strlen(test); // 获取字符串长度 char *s1 = test; // 指向字符串开头 char *s2 = test + length - 1; // 指向字符串结尾 char temp; while (s1 < s2) { // 当两个指针未相遇时 temp = *s1; // 交换字符 *s1 = *s2; *s2 = temp; ++s1; // 移动指针 --s2; } } int main() { char a[] = "abcde"; revstring(a); std::cout << a << std::endl; // 输出: edcba return 0; } ``` 上述代码使用指针操作来实现字符串反转[^2]。 #### 方法三:使用标准库函数`std::reverse` C++标准库提供了`std::reverse`函数,可以直接用于反转`std::string`类型的字符串。 ```cpp #include <iostream> #include <algorithm> // 包含 std::reverse 函数 #include <string> // 包含 std::string 类型 int main() { std::string a = "Hello, World!"; std::reverse(a.begin(), a.end()); // 使用 std::reverse 反转字符串 std::cout << a << std::endl; // 输出: !dlroW ,olleH return 0; } ``` 此代码展示了如何利用标准库函数`std::reverse`来快速反转`std::string`类型的字符串[^3]。 ### 总结 C++中可以通过多种方式实现字符串反转,包括手动循环交换字符、使用指针操作以及调用标准库函数`std::reverse`。每种方法都有其适用场景,选择合适的方法可以提高代码的可读性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值