C++每日一练:小艺照镜子(详解分治法)


前言

大过节的,不想去看人后脑勺,就做点题来玩。挑了小艺照镜子,百分通过~
在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、题目

题目名称:
小艺照镜子

题目描述:
已知字符串str。 输出字符串str中最长回文串的长度。

输入描述:
输入字符串s.(1<=len(str)<=10000)

示例:
输入
abab

输出
3

二、解题

1.分析

这题 初一看挺简单的,先取最大值 0 到 字符长度,然后不停的减小长度比较就行了,结果行不通。纠结好半天,改变思路,先假设最小的情况2或3个,再不停增大,一直到前后不相同。

分三个函数来解释:

函数一:用来测试aba的情况下的回文串

int test_odd(string &s, int m){
    int l = m-1, r = m+1, len = 1;
    while(l >=0  && r < (int)s.length()){
        if(s[l] == s[r]) l--, r++, len += 2;
        else break;
    }
    return len;
}

很简单的代码,m为中间的b,则l就是a,r也是a。初始就是1个回文,找到l和r相同,就加2个。如此从m为1到结束。就找出了所有奇数情况的回文串,并取得最大的一个。

函数二:用来测试baab的情况下的回文串

int test_even(string &s, int m){
    int l = m, r = m+1, len = 0;
    while(l>=0 && r<(int)s.length()){
        if(s[l] == s[r]) l--, r++, len += 2;
        else break;
    }
    return len;
}

这和上在的逻辑差不多,不过就是从s[0] 与s[1] 比较开始罢了,不用解释了吧~

函数三:综合循环一下就好了,就是solution部分。

完整代码:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

int test_odd(string &s, int m){
    int l = m-1, r = m+1, len = 1;
    while(l >=0  && r < (int)s.length()){
        if(s[l] == s[r]) l--, r++, len += 2;
        else break;
    }
    return len;
}

int test_even(string &s, int m){
    int l = m, r = m+1, len = 0;
    while(l>=0 && r<(int)s.length()){
        if(s[l] == s[r]) l--, r++, len += 2;
        else break;
    }
    return len;
}

int solution(std::string s){
    int result = 1;
    // TODO:
    int L = s.length(), res_odd = 0, res_even = 0;
    if (L>=2){
        for (int i=1; i<L; ++i){
            if(s[i-1] == s[i+1]){
                res_odd = max(res_odd, test_odd(s, i));
            };
        }

        for(int i=0; i<L; ++i){
            if (s[i] == s[i+1]){
                res_even = max(res_even, test_even(s, i));
            }
        }
    }
    result = max(result, max(res_odd, res_even));
    return result;
}


int main() {

    std::string s="abc";

    //getline(std::cin, s);;

    int result = solution(s);

    std::cout<<result<<std::endl;

    return 0;
}

看solution部分:因为至少一个字母的情况也能算是回文,所以就默认值为1。
先找出奇数情况下最长的回文,再找出偶数情况下的。
为了尽量减少循环,笔者在调用奇、偶查找之前,先设了一个条件:
奇数情况要求:if(s[i-1] == s[i+1])
偶数情况要求:if (s[i] == s[i+1])
也就是最少要存在回文大于1的情况才去查找是不是有更多的回文。
这样能极大的减少两个查找函数的调用,要不然怕是可能会超时。
最后result = max(result, max(res_odd, res_even));
找出最大值就完事!


总结

把一个较复杂的问题,分解成若干个较简单的问题,这应该也算是分治法了吧~ 分而治之嘛!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无证的攻城狮

如本文对您有用,大爷给打个赏!

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

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

打赏作者

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

抵扣说明:

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

余额充值