C++算法之字符串

字符串

1.字符串比较

题目一:判断两个字符串包含的字符是否完全相同
在这里插入图片描述
我们可以利用哈希表或者数组统计两个数组中每个数字出现的频次,若频次相同,则说明它们包含的字符完全相同。

bool isAnagram(string s,string t)
{
    if(s.length() != t.length())
    {
        return false;
    }
    vector<int>counts(26,0);
    for(int i=0;i<s.length();++i)
    {
        ++counts[s[i]-'a'];
        --counts[t[i]-'a'];
    }
    for(int i=0;i<26;++i)
    {
        if(count[i])
            return false;
    }
    return true;
}

题目二:判断两个字符串是否同构。同构的定义是,可以通过把一个字符串的某些相同的字符转换成
另一些相同的字符,使得两个字符串相同,且两种不同的字符不能够被转换成同一种字符。
在这里插入图片描述
可以将问题转化一下:记录两个字符串每个位置的字符第一次出现的位置,如果两个字符串中相同位置的字符与它们第一次出现的位置一样,那么这两个字符串同构。举例来说,对于“paper”和“title”,假设我们现在遍历到第三个字符“p”和“t”,发现它们第一次出现的位置都在第一个字符,则说明目前位置满足同构。

bool isIsomorphic(string s,string t)
{
    vector<int>s_first_index(256,0),t_first_index(256,0);
    for(int i=0;i<s.length();++i)
    {
        if(s_first_index[s[i]] != t_first_index[t[i]])
        {
            return false;
        }
        s_first_index[s[i]] = t_first_index[t[i]] = i + 1;
    }
    return true;
}

题目三:给定一个字符,求其有多少个回文子字符串。回文的定义是左右对称。

输入是一个字符串,输出一个整数,表示回文字符串的数量
在这里插入图片描述
我们可以从字符串的每个位置开始,向左向右延长,判断存在多少以当前位置为中轴的回文子字符串。

int countSubstrings(string s)
{
    int count = 0;
    for(int i=0;i<s.length();++i)
    {
        count += extendSubstring(s,i,i)//奇数长度
        count += extendSubstring(s,i,i+1);//偶数长度
    }
    return count;
}
int extendSubstring(string s,int l,int r)
{
    int count = 0;
    while(l>=0 && r<s.length() && s[l]==s[r])
    {
        --l;
        ++r;
        ++count;
    }
    return count;
}

题目四:给定一个 0-1 字符串,求有多少非空子字符串的 0 和 1 数量相同。
在这里插入图片描述
从左往右遍历数组,记录和当前位置数字相同且连续的长度,以及其之前连续的不同数字的长度。举例来说,对于 00110 的最后一位,我们记录的相同数字长度是 1,因为只有一个连续 0;我们记录的不同数字长度是 2,因为在 0 之前有两个连续的 1。若不同数字的连续长度大于等于当前数字的连续长度,则说明存在一个且只存在一个以当前数字结尾的满足条件的子字符串。

int countBinarySubstring(string s)
{
    int pre=0,cur=1,count=0;
    for(int i=1;i<s.length();++i)
    {
        if(s[i] == s[i-1])
        {
            ++cur;
        }
        else{
            pre=cur;
            cur=1;
        }
        if(pre >=cur)
        {
            ++count;
        }
    }
    return count;
}

2.字符串理解

题目一:给定一个包含加减乘除整数运算的字符串,求其运算结果,只保留整数。
在这里插入图片描述
如果我们在字符串左边加上一个加号,可以证明其并不改变运算结果,且字符串可以分割成多个 < 一个运算符,一个数字 > 对子的形式;这样一来我们就可以从左往右处理了。由于乘除的优先级高于加减,因此我们需要使用一个中间变量来存储高优先度的运算结果。此类型题也考察很多细节处理,如无运算符的情况,和多个空格的情况等等。

//主函数
int calculate(string s)
{
    int i=0;
    rerturn parseExpr(s,i);
}

//辅函数 - 递归parse从位置i开始的剩余字符串
int parseExpr(const string&s,int&i)
{
    char op='+';
    long left=0,right=0;
    while(i<s.length())
    {
        if(s[i] != ' ')
        {
            long n=parseNum(s,i);
            switch(op)
            {
                case '+':left += right; right=n; break;
                case '-':left += right; right=-n; break;
                case '*':right *=n; break;
                case '/':right /=n; break;
            }
            if(i<s.length())
            {
                op=s[i];
            }
        }
        ++i;
    }
    return left+right;
}

//辅函数 - parse从位置i开始的一个数字
long parseNum(const string&s,int&i)
{
    long n=0;
    while(i<s.length() && isdigit(s[i]))
    {
        n=10 * n + (s[i++] - '0');
    }
    return n;
}

3.字符串匹配

题目一:判断一个字符串是不是另一个字符串的子字符串,并返回其位置。
在这里插入图片描述
使用著名的Knuth-Morris-Pratt(KMP)算法,可以在 O(m + n) 时间利用动态规划完成匹配。

//主函数
int strStr(string haystack,string needle)
{
    int k=-1, n=haystack.length(), p=needle.length();
    if(p==0) return 0;
    vector<int>next(p,-1);//-1表示不存在相同的最大前缀和后缀
    calNext(needle,next);//计算next数组
    for(int i=0;i<n;++i)
    {
        while(k>-1 && needle[k+1] != haystack[i])
        {
            k=next[k];//有部分匹配,往前回溯
        }
        if(needle[k+1] == haystack[i])
        {
            ++k;
        }
        if(k == p-1)
        {
            return i-p+1;//说明k移动到needle的最末端,返回相应的位置
        }
    }
    return -1;
}

//辅函数-计算next数组
void calNext(const string &&needle,vector<int>&next)
{
    for(int j=1, p=-1;j<needle.length();++i)
    {
        while(p>-1 && needle[p+1] != needle[j])
        {
            p=next[p];//如果下一位不同,往前回溯
        }
        if(needle[p+1] == needle[j])
        {
            ++p;//如果下一位相同,更新相同的最大前缀和最大后缀长
        }
        next[j] = p;
    }
}
              

备注:虽然很认真的在撸代码,却是在半知半解的情况下去做的;本来现在的事情应该在学校是就早早完成,深谙其算法原理及实现方法,无奈却是发生在工作一段时间的自省之后;往事不堪回首,现在努力思考,以图尽量做好当下,少发生一些让未来的我会后悔和感到光阴虚度的回忆

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用字符串哈希算法来加速字符串的比较操作。 引用\[1\]中的代码示例展示了一个使用字符串哈希算法C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。其中,哈希值的计算使用了前缀和数组和幂运算。 引用\[2\]中的解释指出,使用字符串哈希的目的是为了比较字符串时不直接比较字符串本身,而是比较它们对应映射的数字。这样可以将子串的哈希值的时间复杂度降低到O(1),从而节省时间。 引用\[3\]中的代码示例也展示了一个使用字符串哈希算法C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。与引用\[1\]中的代码类似,哈希值的计算也使用了前缀和数组和幂运算。 综上所述,字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用前缀和数组和幂运算来计算字符串的哈希值,并通过比较哈希值来判断两个子串是否相等。 #### 引用[.reference_title] - *1* [C++算法题 # 33 字符串哈希](https://blog.csdn.net/weixin_44536804/article/details/123425533)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [字符串哈希(c++)](https://blog.csdn.net/qq_41829492/article/details/120980055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [AcWing 841. 字符串哈希(C++算法)](https://blog.csdn.net/YSA__/article/details/108453403)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

明月醉窗台

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

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

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

打赏作者

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

抵扣说明:

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

余额充值