算法_字符串专题---持续更新

前言

本文将会向你介绍有关字符串的相关题目:最长公共前缀、最长回文子串、二进制求和、字符串相乘。本篇并不是介绍字符串相关的算法,只是将题目要求为字符串类型的归类

最长公共前缀

https://leetcode.cn/problems/longest-common-prefix/description/

题目要求

在这里插入图片描述

题目解析

题目要求找到最长公共前缀,我们很简单地就能想到将字符串中的字符一一比较,返回最长公共前缀,这里采用的是字符串两两比较,先拿第一个字符串与第二个字符串比较,再拿它们的最长公共前缀与第三个字符串比较,最后就能得到最长公共前缀

代码如下

string findCommon(string& s1, string& s2)
{
    int i = 0;
    //注意条件,比较两个字符串,最短的字符串结束就结束了
    while(i < min(s1.size(), s2.size()) && s1[i] == s2[i]) 
    {
        i++;
    }
    return s1.substr(0, i);
}
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs)
    {
        string ret = strs[0];
        for(int i = 1; i < strs.size(); i++)
        {
            ret = findCommon(ret, strs[i]);
        }
        return ret;
    }
};

最长回文子串

https://leetcode.cn/problems/longest-palindromic-substring/

题目要求

在这里插入图片描述

题目解析

给一个字符串,要求出字符串中最长的回文子串,即需要在一个字符串中找到中间对称的子串,aba,bab都是关于中间对称,那么我们可以对所有的可能为中点的点遍历一遍,这样才能找出最长的,这里采用中心扩展算法,即遍历每个点(每次把该点当作中点),从该点开始向左向右进行移动,如果left[i] = right[i],则继续向左向右移动,直到不相同位置,那么就可以找到以某个点为中心对称的字符串

注意点:分奇偶

当出现类似回文子串b a b这种格式,是需要将left = right = i(i:遍历的每个点),即子串字符数为奇数情况 当出现类似回文串b b这种格式,是需要将left = i,right = i + 1 即子串字符数为偶数情况

在这里插入图片描述

代码如下

class Solution {
public:
    string longestPalindrome(string s) 
    {
        int n = s.size();
        int len = 0;    //最长回文串长度
        int begin = 0;  //回文串的起始位置
        //遍历所有可能为中点的点
        for(int i = 0; i < n; i++)
        {
            //字符串为奇数个字符
            int left = i, right = i;
            while(left >= 0 && right <= n && s[left] == s[right])
            {
                left--;
                right++;
            }
            if(right - left - 1 > len)
            {
                len = right - left - 1;
                begin = left + 1;
            }
            //字符串为偶数个字符
            left = i, right = i + 1;
            while(left >= 0 && right <= n && s[left] == s[right])
            {
                left--;
                right++;
            }
            if(right - left - 1 > len)
            {
                len = right - left - 1;
                begin = left + 1;
            }
        }
        return s.substr(begin, len);
    }
};

二进制求和

https://leetcode.cn/problems/add-binary/

题目要求

在这里插入图片描述

题目解析

给两个字符串,按照二进制加法相加,我们很自然地能想到遍历每个字符,然后按照二进制相加,模拟加法过程即可

注意点一:字符串模拟加法

在正常加法中,我们都是从低位,即图中下标为3的位置相加直到加到高位,其中还包含低位向高位的进位,因此模拟过程中也需要把进位给模拟出来,因此我们必须也要从下标为3的位置字符开始相加 也可以看看另一道类似解法的题

两数相加,这在篇文章链表专题中也提到过

在这里插入图片描述

注意点二:结束条件

当其中一个字符串结束,都不能作为结束条件,而且当两个字符串都遍历完了,可能进位不为0,也不能结束 ## 代码如下
class Solution {
public:
    string addBinary(string a, string b) 
    {
        int t = 0; //进位
        string ret;
        int cur1 = a.size() - 1;
        int cur2 = b.size() - 1;
        while(cur1 >= 0 || cur2 >= 0 || t > 0)
        {
            if(cur1 >= 0)
            {
                t += a[cur1] - '0';
                cur1--;
            }
            if(cur2 >= 0)
            {
                t += b[cur2] - '0';
                cur2--;
            }
            ret += t % 2 + '0';
            t/=2;
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

字符串相乘

https://leetcode.cn/problems/multiply-strings/

题目要求

在这里插入图片描述

题目解析

这道题容易想到的解法就是以其中一个字符串每一位去乘以另一个字符串,然后将每次相乘的结果再相加,如下图所示
但这种解法并不好写,因此将会介绍另一种不好想到,但是好写的解法
在这里插入图片描述

解法二

无进位相乘再相加,再处理进位
在这里插入图片描述

由于给定字符串下标的顺序与我们实际乘法+进位的顺序相反,所以我们先将给定字符串逆序一下,注意以后碰到带有进位类似的题目,最好也是先逆序一下

一、模拟乘法相加

直接将两个字符串中的字符 - '0'相乘再相加即可,注意符号+=
        for (int i = 0; i < sz1; i++)
        {
            for (int j = 0; j < sz2; j++)
            {
                tmp[i + j] += ((num1[i] - '0') * (num2[j] - '0'));
            }
        }

二、模拟进位操作

先用t保存相乘再相加的结果,将个位上的数留下,十位上的数进位
        //进位操作
        string ret;
        int t = 0, cur = 0; //进位
        while(cur < sz1 + sz2 - 1 || t != 0)
        {
            if(cur < sz1 + sz2 - 1) t += tmp[cur++];
            ret += t % 10 + '0';
            t /= 10;
        }

三、去掉前导0

如果123 乘 0 按照我们以上的模拟乘法,将会得出000,因此需要把前两个0给去掉
        while(ret.size() > 1 && ret.back() == '0') ret.pop_back();

注意:当进位不为0的时候也不能结束循环,因为可能存在两个字符串最后一位为:3 + 7,进位为 1
最后逆序保存结果的字符串即可

代码如下

class Solution {
public:
    string multiply(string num1, string num2)
    {
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        int sz1 = num1.size();
        int sz2 = num2.size();
        vector<int> tmp(sz1 + sz2 - 1);   //无进位相乘再相加后的数组
        for (int i = 0; i < sz1; i++)
        {
            for (int j = 0; j < sz2; j++)
            {
                tmp[i + j] += ((num1[i] - '0') * (num2[j] - '0'));
            }
        }
        //进位操作
        string ret;
        int t = 0, cur = 0; //进位
        while(cur < sz1 + sz2 - 1 || t != 0)
        {
            if(cur < sz1 + sz2 - 1) t += tmp[cur++];
            ret += t % 10 + '0';
            t /= 10;
        }
        //去掉前导零
        while(ret.size() > 1 && ret.back() == '0') ret.pop_back();
        reverse(ret.begin(), ret.end());
        return ret;
    }
};
  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
BF算法(Brute-Force算法),也称为朴素匹配算法,是一种简单直观的字符串匹配算法。它的基本思想是从主串的第一个字符开始,依次与模式串的每个字符进行比较,如果匹配成功,则继续比较下一个字符,否则主串指针后移一位,重新开始匹配。这个过程类似于暴力破解密码的过程,因此也被称为暴力匹配算法。 下面是BF算法的C语言实现: ```c #include <stdio.h> #include <string.h> int BF(char* s, char* p) { int i = 0, j = 0; int s_len = strlen(s); int p_len = strlen(p); while (i < s_len && j < p_len) { if (s[i] == p[j]) { i++; j++; } else { i = i - j + 1; j = 0; } } if (j == p_len) { return i - j; } else { return -1; } } int main() { char s[] = "hello world"; char p[] = "world"; int pos = BF(s, p); if (pos != -1) { printf("匹配成功,位置为:%d\n", pos); } else { printf("匹配失败\n"); } return 0; } ``` 在上面的代码中,BF函数接受两个参数,分别是主串s和模式串p。在函数中,我们使用两个指针i和j分别指向主串和模式串的第一个字符,然后依次比较它们的字符是否相等。如果相等,则继续比较下一个字符,否则主串指针后移一位,重新开始匹配。如果模式串匹配成功,则返回匹配的位置,否则返回-1。 需要注意的是,BF算法的时间复杂度为O(m*n),其中m和n分别为主串和模式串的长度。因此,当主串和模式串的长度较大时,BF算法的效率会比较低。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fan_558

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值