您的位置:首页 > 编程语言

对称子字符串的最大长度

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

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

 

解法一:O(n3)的算法

现在我们试着来得到对称子字符串的最大长度。最直观的做法就是得到输入字符串的所有子字符串,并逐个判断是不是对称的。如果一个子字符串是对称的,我们就得到它的长度。这样经过比较,就能得到最长的对称子字符串的长度了。于是,我们可以写出如下代码:

 

// IsSymmetricalString2.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include <iostream>

using namespace std;

 /************************************************

 * 判断一个字符串是否是对称的

 *************************************************/

bool IsSymmetricalString(char* pstart,char* pend)

{

 if (pstart==NULL || pend==NULL || pstart>pend)

 {

  return false;

 }

 while (pstart<pend)

 {

  if (*pstart!=*pend)

  {

   return false;

  }

  pstart++;

  pend--;

 }

 return true;

}

 /*************************************************

 * 求最大对称子串的长度

 **************************************************/

int MaxSymmetricalSubstringLenth(char *pstring)

{

 if (pstring==NULL)

 {

  return 0;

 }

 int maxLength=1;

 int length=strlen(pstring);

 char* pstart=pstring;

 while (pstart<&pstring[length-1])

 {

  char* psecond=pstart+1;

  while (psecond<=&pstring[length-1])

  {

   if (IsSymmetricalString(pstart,psecond))

   {

    int tempLength=psecond-pstart+1;

    if (tempLength>maxLength)

    {

     maxLength=tempLength;

    }

   }

   psecond++;

  }

  pstart++;

 }

 return maxLength;

}

int _tmain(int argc, _TCHAR* argv[])

{

 cout<<"Please Enter Your String(the length must <1000 ):"<<endl;

 char* yourstring = new char[1000];

 cin>>yourstring;

 cout<<"The Max Symmetrical SubString Length in Your String is:"<<endl;

 cout<<MaxSymmetricalSubstringLenth(yourstring)<<endl;

 system("pause");

 return 0;

}

 

 

[html] view
plaincopy

// IsSymmetricalString2.cpp : 定义控制台应用程序的入口点。  

//  

  

#include "stdafx.h"  

#include <iostream>  

using namespace std;  

  

 /************************************************  

 * 判断一个字符串是否是对称的  

 *************************************************/  

  

bool IsSymmetricalString(char* pstart,char* pend)  

{  

    if (pstart==NULL || pend==NULL || pstart>pend)  

    {  

        return false;  

    }  

    while (pstart<pend)  

    {  

        if (*pstart!=*pend)  

        {  

            return false;  

        }  

        pstart++;  

        pend--;  

    }  

    return true;  

}  

  

 /*************************************************  

 * 求最大对称子串的长度  

 **************************************************/  

int MaxSymmetricalSubstringLenth(char *pstring)  

{  

    if (pstring==NULL)  

    {  

        return 0;  

    }  

    int maxLength=1;  

    int length=strlen(pstring);  

    char* pstart=pstring;  

    while (pstart<&pstring[length-1])  

    {  

        char* psecond=pstart+1;  

        while (psecond<=&pstring[length-1])  

        {  

            if (IsSymmetricalString(pstart,psecond))  

            {  

                int tempLength=psecond-pstart+1;  

                if (tempLength>maxLength)  

                {  

                    maxLength=tempLength;  

                }  

            }  

            psecond++;  

        }  

        pstart++;  

    }  

    return maxLength;  

}  

  

  

int _tmain(int argc, _TCHAR* argv[])  

{  

    cout<<"Please Enter Your String(the length must <1000 ):"<<endl;  

    char* yourstring = new char[1000];  

    cin>>yourstring;  

    cout<<"The Max Symmetrical SubString Length in Your String is:"<<endl;  

    cout<<MaxSymmetricalSubstringLenth(yourstring)<<endl;  

  

  

    system("pause");  

    return 0;  

}  

 

我们来分析一下上述方法的时间效率。由于我们需要两重while循环,每重循环需要O(n)的时间。另外,我们在循环中调用了IsSymmetrical,每次调用也需要O(n)的时间。因此整个函数的时间效率是O(n3)。

通常O(n3)不会是一个高效的算法。如果我们仔细分析上述方法的比较过程,我们就能发现其中有很多重复的比较。假设我们需要判断一个子字符串具有aAa的形式(A是aAa的子字符串,可能含有多个字符)。我们先把pFirst指向最前面的字符a,把pLast指向最后面的字符a,由于两个字符相同,我们在IsSymtical函数内部向后移动pFirst,向前移动pLast,以判断A是不是对称的。接下来若干步骤之后,由于A也是输入字符串的一个子字符串,我们需要再一次判断它是不是对称的。也就是说,我们重复多次地在判断A是不是对称的。

造成上述重复比较的根源在于IsSymmetrical的比较是从外向里进行的。在判断aAa是不是对称的时候,我们不知道A是不是对称的,因此需要花费O(n)的时间来判断。下次我们判断A是不是对称的时候,我们仍然需要O(n)的时间。

解法二:O(n2)的算法

如果我们换一种思路,我们从里向外来判断。也就是我们先判断子字符串A是不是对称的。如果A不是对称的,那么向该子字符串两端各延长一个字符得到的字符串肯定不是对称的。如果A对称,那么我们只需要判断A两端延长的一个字符是不是相等的,如果相等,则延长后的字符串是对称的。因此在知道A是否对称之后,只需要O(1)的时间就能知道aAa是不是对称的。

我们可以根据从里向外比较的思路写出如下代码

// MaxSymmetricalSubstringLenth.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include<iostream>

 #include<string>

 using namespace std;

 

 /*********************************************************************

 * 计算字符串最大对称子串的长度

 *********************************************************************/

 int GetLongestSymmetricalLength_2(char* pString)

 {

  if(pString == NULL)

   return 0;

  int symmeticalLength = 1;

  char* pChar = pString;

  while(*pChar != '\0')

  {

   // Substrings with odd length(奇数)

   char* pFirst = pChar - 1;

   char* pLast = pChar + 1;

   while(*pLast != '\0' && *pFirst == *pLast)

   {

    pFirst--;

    pLast++;

   }

   int newLength = pLast - pFirst - 1;

   if(newLength > symmeticalLength)

    symmeticalLength = newLength;

   // Substrings with even length(偶数)

   pFirst = pChar;

   pLast = pChar + 1;

   while(  *pLast != '\0' && *pFirst == *pLast)

   {

    pFirst--;

    pLast++;

   }

   newLength = pLast - pFirst - 1;

   if(newLength > symmeticalLength)

    symmeticalLength = newLength;

   pChar++;

  }

  return symmeticalLength;

 }

 

 int main()

 {

     cout<<"Please Enter Your String:"<<endl;

     char *yourstring = new char[1000];

     cin>>yourstring;

 

     cout<<"The Max Symmetrical SubString Length is:"<<endl;

     cout<<GetLongestSymmetricalLength_2(yourstring)<<endl;

 

     delete[] yourstring;

  system("pause");

     return 0;

}

 

[html] view
plaincopy

// MaxSymmetricalSubstringLenth.cpp : 定义控制台应用程序的入口点。  

//  

  

#include "stdafx.h"  

  

#include<iostream>  

 #include<string>  

 using namespace std;  

   

 /*********************************************************************  

 * 计算字符串最大对称子串的长度  

 *********************************************************************/  

  

 int GetLongestSymmetricalLength_2(char* pString)  

 {  

     if(pString == NULL)  

         return 0;  

     int symmeticalLength = 1;  

     char* pChar = pString;  

     while(*pChar != '\0')  

     {  

         // Substrings with odd length(奇数)  

         char* pFirst = pChar - 1;  

         char* pLast = pChar + 1;  

         while(*pLast != '\0' && *pFirst == *pLast)  

         {  

             pFirst--;  

             pLast++;  

         }  

         int newLength = pLast - pFirst - 1;  

         if(newLength > symmeticalLength)  

             symmeticalLength = newLength;  

         // Substrings with even length(偶数)  

         pFirst = pChar;  

         pLast = pChar + 1;  

         while(  *pLast != '\0' && *pFirst == *pLast)  

         {  

             pFirst--;  

             pLast++;  

         }  

         newLength = pLast - pFirst - 1;  

         if(newLength > symmeticalLength)  

             symmeticalLength = newLength;  

         pChar++;  

     }  

     return symmeticalLength;  

  

 }  

  

  

   

 int main()  

 {  

     cout<<"Please Enter Your String:"<<endl;  

     char *yourstring = new char[1000];  

     cin>>yourstring;  

   

     cout<<"The Max Symmetrical SubString Length is:"<<endl;  

     cout<<GetLongestSymmetricalLength_2(yourstring)<<endl;  

   

     delete[] yourstring;   

  

     system("pause");  

     return 0;  

  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 编程