算法笔记(八)——字符串

最长公共前缀

题目:最长公共前缀

在这里插入图片描述
思路

  • 两两比较,将每两个的子串和未比较的字符串相比较;
    在这里插入图片描述

C++代码

class Solution 
{
public:
    string Common(string& s1, string& s2)
    {
        int i = 0;
        while(i < min(s1.size(), s2.size()) && s1[i] == s2[i])
            i++;
        
        return s1.substr(0, i);
    }
    string longestCommonPrefix(vector<string>& strs) 
    {
        // 两两比较
        string ret = strs[0];
        for(int i = 1; i < strs.size(); i++)
            ret = Common(ret, strs[i]);
        
        return ret;
    }
};

最长回文子串

题目:最长回文子串

在这里插入图片描述
思路

  • 中心扩散:计算以每一个字母为中心向左右两边扩散的奇数和偶数的回文串最大长度和该回文串的起始位置

C++代码

class Solution 
{
public:
    string longestPalindrome(string s) 
    {
        int begin = 0, len = 0;
        int n = s.size();
        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)
            {
                begin = left + 1;
                len = right - left - 1;
            }

            // 偶数扩展
            left = i, right = i + 1;
            while(left >= 0 && right < n && s[left] == s[right])
            {
                left--, right++; 
            }
            if(right - left - 1 > len)
            {
                begin = left + 1;
                len = right - left - 1;
            }
        }

        return s.substr(begin, len);
    }
};

二进制求和

题目:二进制求和

在这里插入图片描述
思路

  • 从字符串右边开始累加进位拼接字符串,计算完之后记得翻转字符串

C++代码

class Solution 
{
public:
    string addBinary(string a, string b) 
    {   
        string res;

        int cur1 = a.size() - 1;
        int cur2 = b.size() - 1;
        int t = 0; // 进位

        while(cur1 >= 0 || cur2 >= 0 || t)
        {
            if(cur1 >= 0) t += a[cur1--] - '0';
            if(cur2 >= 0) t += b[cur2--] - '0';   
            res += t % 2 + '0';
            t /= 2;
        }
        reverse(res.begin(), res.end());

        return res;
    }
};

字符串相乘

题目:字符串相乘

在这里插入图片描述
思路

  • 计算两数相乘的时候,先不考虑进位,等到所有结果计算完毕之后再去进位

C++代码

class Solution 
{
public:
    string multiply(string num1, string num2) 
    {
        int n = num1.size(), m = num2.size();

        // 反转两个字符串
        reverse(num1.begin(), num1.end());   
        reverse(num2.begin(), num2.end());   

        // 存放每一位相乘的结果
        vector<int> tmp(n + m - 1);

        // 无进位相乘
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');
            }
        }

        // 处理进位
        int cur = 0, t = 0;
        string ret;
        while(cur < n + m - 1 || t != 0)
        {
            if(cur < n + m + 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;
    }
};
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法C++代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值