九度笔记之 1252:回文子串

题目描述:

输入一个字符串,输出该字符串中对称的子字符串的最大长度。

比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。

输入:

存在多组数据,每组数据一行字符串,长度不大于100。

输出:

输出回文子串的最大长度。

样例输入:

google

样例输出:

4



算法分析

 本来打算用《最长合法括号序列1》中的算法,利用动态规划做,但是对于例如“aaa”的情况该算法就无效了

 因为括号必须是左右一对同时出现,左边的必为”(“,右边的必为”)“,所以当出现str[pos]==”(”或 str[sympos]<0 或str[sympos]==”)”的情况时,str[pos]位置的符号不可能再和dp[pos-1]合法子括号序列的子字符串构成合法括号序列。

(()(

)()(

())

)())



对于回文字符串,则会出现以下情况

aaa   

      dp[1]=2 ,    

      pos==2时,sympos== -1,得到dp[pos]=1 实际上dp[pos]=3

       因为a[1]相当于一个回文字符串,str[0]==str[2],dp[pos]=3

abadabad

      dp[6]=7,     

      pos==8时,sympos== -1,得到dp[pos]=1 实际上dp[pos]=5

      因为abadaba中的子字符串aba为一个回文字符串,str[3]==str[7],故dp[pos]=5

 

公共子序列查找

新的思路就是,如果字符串s中含有回文字符串,回文字符串一定为该字符串的逆序列rs和该字符串s的公共子序列,如下所示。

      google        s

  elgoog      sr   

 

                 abamngnm    s

                       mngnmaba   sr

  mngnmaba       sr

 算法实现就很简单了,从sr的某个位置开始,s从0开始逐个字符比较,记录最长的公共序列。

另外一种快速的 manach算法 参见 1252:回文子串

源代码:

程序中需要注意的是srbegin的每次循环,temLen都要重新置为0

srid的每次循环结束后,也要判断一下temLen和maxLen的大小,

 google      s

elgoog       sr

在sid==3,srid==5时,

sr.at(srid)==s.at(sid)

temLen++;

srid++;sid++;

循环退出,此时temLen==4,maxLen==0

还有就是考虑到sr需要前向错位,后向错位来比较,所以需要将s,sr反过来比较一下。参看int getMaxNum(std::string &s)


#include <iostream>
#include <string>
using namespace std;
int getMaxNum(std::string &s,std::string &sr){
    int sLen = s.size();
    int maxLen = 0;
    int temLen = 0;
    /*
     *   google   s
     * elgoog    sr
     */
    /*
     * abacdefgfedcmnm
     * mnmcdefgfedcaba
     */
    int srbegin = 0;
    while(srbegin < sLen){// sr start from i compare s
        int srid = srbegin;
        int sid = 0;
        temLen = 0;  //attention
        while(srid < sLen){
            if(sr.at(srid)==s.at(sid)){
                temLen++;
            }else{
                if(temLen > maxLen)
                    maxLen = temLen;
                temLen=0;
                //break;
            }
            srid++;
            sid++;
        }//while(srid < sLen)
        if(temLen>maxLen)     //attention srid==sLen must be considered for "google"
            maxLen = temLen;
        srbegin++;
    }
    return maxLen;
}
 
int getMaxNum(std::string &s){
    std::string sr(s.rbegin(),s.rend());
    int maxLen = 0;
    maxLen = getMaxNum(s,sr);
    int rMaxLen = getMaxNum(sr,s);
    if(rMaxLen>maxLen)
        return rMaxLen;
    else
        return maxLen;
}
 
 
void test(){
    std::string s = "ab";
    std::string sr(s.rbegin(),s.rend());
    std::cout<<sr<<std::endl;
}
void judo(){
    std::string s;
    //int temLen = 0;
    while(std::cin>>s){
        std::cout<<getMaxNum(s)<<std::endl;
    }
}
int main() {
    //cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    judo();
    return 0;
}
 
/**************************************************************
    Problem: 1252
    User: KES
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值