zoukankan      html  css  js  c++  java
  • 【算法25】对称子字符串的最大长度

      【题   目】输入一个字符串,输出该字符串中最大对称子串的长度。例如输入字符串:“google”,该字符串中最长的子字符串是“goog”,长度为4,因而输出为4。

      【思 路1】一看这题就是遍历!没错,我们最直观的往往也是最容易实现的,这里我们暂且不考虑效率的问题。我们的基本思路是:我们如果有一个判断一个字符串是不是对称的函数的话,我们就可以用这个子函数逐一检查原字符串中所有的字符串,然后输出长度最大的即可。

      (1)怎样判断一个字符串是不是对称的字符串?我们可以用两个指针分别指向字符串的第一个字符和最后一个字符,判断是否相等,如果不等直接返回false,如果为真则接着比较下一对字符。(2)如果遍历遍历原字符串的所有子串,首先我们让一个指针从头至尾遍历,对于这个指针的每一个字符,我们在用另一个指针逐一指向它后面的每一个字符即可。好了,两个问题都解决了,我们可以写出如下的代码:

     1 #include<iostream>
    2 #include<string>
    3 #include<cstring>
    4 using namespace std;
    5
    6 /************************************************
    7 * 判断一个字符串是否是对称的
    8 *************************************************/
    9 bool IsSymmetricalString(char* pstart,char* pend)
    10 {
    11 if(pstart == NULL || pend == NULL || pstart > pend)
    12 return false;
    13
    14 while(pstart < pend)
    15 {
    16 if(*pstart != *pend)
    17 {
    18 return false;
    19 }
    20 else
    21 {
    22 pstart++;
    23 pend--;
    24 }
    25 }
    26
    27 return true;
    28 }
    29
    30
    31 /*************************************************
    32 * 求最大对称子串的长度
    33 **************************************************/
    34 int MaxSymmetricalSubstringLenth(char *pstring)
    35 {
    36 if(pstring == NULL)
    37 return 0;
    38
    39 int maxlength = 1;
    40
    41 int length = strlen(pstring);
    42 char* pfirst = pstring;
    43 while(pfirst < &pstring[length - 1])
    44 {
    45 char* psecond = pfirst + 1;
    46 while(psecond <= &pstring[length - 1])
    47 {
    48 if(IsSymmetricalString(pfirst,psecond))
    49 {
    50 int templength = psecond - pfirst + 1;
    51 if(templength > maxlength)
    52 {
    53 maxlength = templength;
    54 }
    55 }
    56
    57 psecond++;
    58 }
    59
    60 pfirst++;
    61 }
    62
    63 return maxlength;
    64 }
    65
    66 int main()
    67 {
    68 cout<<"Please Enter Your String(the length must <1000 ):"<<endl;
    69 char* yourstring = new char[1000];
    70 cin>>yourstring;
    71
    72 cout<<"The Max Symmetrical SubString Length in Your String is:"<<endl;
    73 cout<<MaxSymmetricalSubstringLenth(yourstring)<<endl;
    74
    75 return 0;
    76 }

      运行结果如下:

      反思:我们现在来分析一下该算法的时间复杂度,首先遍历原字符串的所有子串有两个循环,这个时间复杂度是O(n2),我们在这两层循环之间有一个判断给定字符串是不是对称的子函数,这个子函数的时间复杂度是O(n),所以总的时间复杂度是O(n3).由于我们是由外向内判断一个字符串是不是对称的,那么对于形如aba的字子串(b可以含有很多字符),我们判断aa相等后,还得判断b是否是对称;而在判断子串b的时候还得再判断一次,换句话说有很多的子串我们是重复判断的。那么我们能不能消除这种重复呢?、


      【思 路2】根据上面的分析,我们很容易想到,如果我们从内向外比较字符,那么对于aba型的字符串,如果我们判断了b是对称的,只需要再左右各移一位就可以判断下一个字符串是否是对称的,这样我们就能避免重复;然而我们需要注意的是,对于原字符串中每一个字符有两种情况,一种是子串是以单个字符为中心对称分布的,换句话说,子串的长度是奇数;另一种情况是子串以两个字符串为中心,即子串的长度是偶数。至此我们就可以写出如下的代码:

     1 #include<iostream>
    2 #include<string>
    3 using namespace std;
    4
    5 /*********************************************************************
    6 * 计算字符串最大对称子串的长度
    7 *********************************************************************/
    8 int MaxSymmetricalSubstringLenth(char* pstring)
    9 {
    10 int maxlength = 1;
    11
    12 char* pchar = pstring + 1;
    13 while(*pchar != '\0')
    14 {
    15 //以该字符串为中心,子串长度为奇数
    16 char *pfirst = pchar - 1;
    17 char *psecond = pchar + 1;
    18 while(pfirst > pstring && psecond < &pstring[strlen(pstring) - 1] && *pfirst == *psecond)
    19 {
    20 pfirst--;
    21 psecond++;
    22 }
    23
    24 int templength = psecond - pfirst + 1;
    25 if(templength > maxlength)
    26 {
    27 maxlength = templength;
    28 }
    29
    30
    31 //字该字符及之后的字符两个为中心,子串为偶数
    32 pfirst = pchar - 1;
    33 psecond = pchar;
    34 while(pfirst > pstring && psecond < &pstring[strlen(pstring) - 1] && *pfirst == *psecond)
    35 {
    36 pfirst--;
    37 psecond++;
    38 }
    39
    40 templength = psecond - pfirst + 1;
    41 if(templength > maxlength)
    42 {
    43 maxlength = templength;
    44 }
    45
    46 pchar++;
    47 }
    48
    49 return maxlength;
    50 }
    51
    52 int main()
    53 {
    54 cout<<"Please Enter Your String:"<<endl;
    55 char *yourstring = new char[1000];
    56 cin>>yourstring;
    57
    58 cout<<"The Max Symmetrical SubString Length is:"<<endl;
    59 cout<<MaxSymmetricalSubstringLenth(yourstring)<<endl;
    60
    61 delete[] yourstring;
    62 return 0;
    63 }

      测试结果如下:

      效率分析:这种算法首先需要遍历一边字符串,外层为n,对于每一个字符,需要从该字符开始有中间到两边遍历一遍,因而总的时间复杂度是O(n2).


    References:

    程序员面试题精选100题:http://zhedahht.blog.163.com/blog/static/25411174201063105120425/

    注:

    1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

    2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。

  • 相关阅读:
    VI服务器
    LabVIEW编程技巧:网络通信中如何获取计算机名称、IP地址等信息
    Labview 局部变量
    TL431的几种常用用法
    s8550引脚图与电路图汇总分析
    齐二TK6916/20/26/32系列数控落地铣镗床简介8
    VBA Format函数 自定义格式中 0/#的区别
    [Excel VBA] Shape.Type属性名称及对应值列表
    如何另存(保存)不含宏
    我想一次性选择(或复制)工作簿中的多张表到另一工作簿
  • 原文地址:https://www.cnblogs.com/python27/p/2291977.html
Copyright © 2011-2022 走看看