简单的 字符串比较函数 易懂 复杂度

本文详细介绍了三种高效的字符串匹配算法,包括简单循环匹配、改进的KMP算法和Boyer-Moore算法,分析了它们的时间复杂度,并讨论了算法在实际应用中的优劣。此外,还提供了代码实现和复杂度分析,帮助读者理解如何在不同场景下选择合适的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.简单的字符串匹配函数

简单的字符串匹配很简单,就是一个两重循环。

算发一:

#include<stdio.h>

#include<string.h>

 

char s[51],t[11];

int next[11];

int cnt[11];

 

void index(char*s,char *t,int pos)

{

       int i,j,k;

    int x = 0;

    int len1 = strlen(s);

    int len2 = strlen(t);

 

    for(i=pos;i<len1;i++)

    {

        k = i;

        for(j=0;j<len2;j++)

        {           

            if(s[k++]!=t[j])

                break;

        }

        if(j>=len2)

        {

            cnt[x++] = i;

        }

    }

}

 

int main(void)

{

    memset(cnt,-1,11*sizeof(int));

    gets(s);

    gets(t);

    int pos;

    scanf("%d",&pos);

       index(s,t,pos);

    for(int i=0;cnt[i]!=-1;i++)

    {

        printf("    %d",cnt[i]);

    }

return 0;

}

下面分析其复杂度:  

除了在index2,index4,index6,index10四处字符串比较了多次外,在其他地方字符串只比较了一次,总共的比较次数为(n-m+1)+(m-1)+others,others为红色的部分,也就是说其复杂度接近O(n+m)。

假设主串的长度为n,模式串的长度为m,在最坏情况下,对于主串(n-m+1)中的每一个字符,都要和模式中的字符匹配m次,后面的每个字符的匹配次数总共为(1+2+…+(m-1))=m(m-1)/2,则总的匹配次数为(n-m+1)*m+ m(m-1)/2,也即算发复杂度为O(n*m)。

 

  上面这种方法比较的直观和简单,但是复杂度却很高,效率低下,很难应用于实际,下面有个改进的版本,功能是输出第一次出现子串的索引。

算发二:

#include <stdio.h>

#include <string.h>

 

char s[51],t[11];

int next[11];

 

int index(char *s,char *t,int pos)

{

    int i =pos-1;

    int j = 0;

    int len1=  strlen(s);

    int len2 =strlen(t);

 

   while(i<len1&&j<len2)

    {

       if(s[i]==t[j])

        {

            i++;

            j++;

        }

        else

        {

            i -=j-1;

            j =0;

        }

    }

       if(j>=len2)

    {

       returni-len2;

    }

    else

       return-1;

}

 

int main(void)

{

    gets(s);

    gets(t);

    int pos;

   scanf("%d",&pos);

 

    int no =index(s,t,pos);

    if(no>0)

       printf("String s contains substring t at index of %d~~\n",no);

    else

       printf("String s does not contain substring t~~\n");

    return 0;

}

下面让我们来分析其复杂度,

除了在index2,index4,index6,index10四处字符串比较了多次外,在其他地方字符串只比较了一次,假设最终查找到子串的位置为index,在一次查找过程中,最终的比较次数为(index+len2-1)+others,这个others就是之前有过的多次比较的结果。其复杂度接近O(n+m)。在最坏的情况下,其复杂度也是O(n*m)。

算发三:

#include <stdio.h>

#include <string.h>

 

char s[51],t[11];

int next[11];

int cnt[11];

 

void index(char *s,char *t,int pos)

{

   intx=0;

   int i = pos-1;

   int j = 0;

   int len1 =  strlen(s);

   int len2 = strlen(t);

 

   for(i=pos-1;i<len1;)

    {

       while(i<len1&&j<len2)

       {

           if(s[i]==t[j])

           {

                i++;

                j++;

           }

           else

           {

               i -= j-1;

               j = 0;

           }

       }

          if(j>=len2)

       {

          cnt[x++] = i-len2;

             i -= len2-1;

             j = 0;

       }

   }   

}

 

int main(void)

{

   memset(cnt,-1,11*sizeof(int));

   gets(s);

   gets(t);

   int pos;

   scanf("%d",&pos);

 

   index(s,t,pos);

  

   for(int i=0;cnt[i]!=-1;i++)

    {

       printf("    %d",cnt[i]);

    }

   printf("\n");

   return 0;

}

<think>好的,用户想在C++中定义一个处理字符串函数,我需要给出一个例子。首先,我得确认用户的需求是什么。处理字符串函数有很多种,比如拼接、反转、查找子串等等。考虑到用户可能刚开始学习,最好选一个简单常见的例子,比如反转字符串或者转换大小写。 接下来,我要回忆C++中处理字符串的方法。C++中常用的字符串类有std::string,属于<string>头文件。处理函数一般会接受一个std::string参数,返回处理后的结果。比如,定义一个反转字符串函数,可以用循环或者标准库中的算法。 然后,我需要考虑代码的正确性。比如使用std::reverse算法来反转字符串,这样代码简洁易懂。另外,要确保包含必要的头文件,比如<algorithm>和<string>。还要注意函数的参数传递方式,按值传递还是引用。这里反转函数可能需要修改副本,所以按值传递可能更合适,或者使用const引用然后创建副本。 用户可能还需要了解如何调用这个函数,所以在示例代码中应该包含main函数里的调用示例。例如,定义一个reverse_string函数,然后在main中调用它并输出结果。 另外,用户可能对参数类型和返回值不太清楚,需要明确说明函数的输入输出。同时,提醒用户注意包含必要的头文件,以及使用命名空间std,或者避免使用using namespace std,但示例中可能为了简洁而使用。 还要检查是否有相关引用可以引用,但根据提供的引用内容,可能没有直接相关的,所以可能不需要添加引用标识。不过需要确保回答中提到的内容如果有涉及引用的地方正确标注。 最后,生成相关问题的时候,要考虑用户可能进一步的问题,比如字符串的其他操作、性能优化、参数传递方式等,这样能帮助用户深入学习。</think>在C++中定义处理字符串函数时,通常使用$std::string$作为参数和返回值类型。以下是一个包含字符串反转和大小写转换的示例: ```cpp #include <string> #include <algorithm> // 包含reverse算法 #include <cctype> // 包含tolower/toupper // 反转字符串 std::string reverse_string(std::string str) { std::reverse(str.begin(), str.end()); return str; } // 转换为全大写 std::string to_upper(const std::string& s) { std::string result; for (char c : s) { result += static_cast<char>(std::toupper(c)); } return result; } // 示例使用 int main() { std::string test = "Hello World"; std::cout << reverse_string(test); // 输出"dlroW olleH" std::cout << to_upper(test); // 输出"HELLO WORLD" return 0; } ``` ### 关键点说明: 1. **参数传递**:反转函数使用值传递创建副本,避免修改原字符串;大写转换使用$const\ std::string\&$避免拷贝[^3] 2. **标准库算法**:$std::reverse$用于高效反转序列,时间复杂度$O(n)$ 3. **类型转换**:字符处理使用$std::toupper$配合类型转换,确保跨平台兼容性 4. **返回值优化**:现代C++编译器支持返回值优化(RVO),无需担心临时对象拷贝问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值