您的位置:首页 > 其它

对称子字符串的最大长度

2012-09-03 22:06 260 查看
【题 目】输入一个字符串,输出该字符串中最大对称子串的长度。例如输入字符串:“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/。对解题思路有任何建议,欢迎在评论中告知。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: