Longest Palindromic Substring - 一题多解

题意是寻找一个字符串的最大回文字串,最简单的是n3方的算法,由于字符串最大长度为1000,所以这个方法很危险而且不科学。

紧接着想到的是一个n方的算法:回文子串是从中间向两边产生的,那么对于每个字符考察这个字符往外的所有可能不就可以找到以这个字符为中心的最长回文子串了吗?当然要考虑偶数的情况,即那个中心不在字母上,而这种情况的字符又一定满足中心的两个字符是相等的。所以在第一遍寻找奇数最长回文字符的时候记录下有可能形成偶数回文字符的数组下标,统一规定为两个字母下标较小的那个。

按照以上想法编码AC如下:

 1 class Solution {
 2 public:
 3     string longestPalindrome(string s) {
 4         string resstring;
 5         int maxlen=0;
 6         int maxindex=0;
 7         int n=s.length();
 8         int doublestring[1002];
 9         if(n==1)
10             return s;
11         for(int i=0;i<n;i++)
12         {
13             int index=i;int delt=1;
14             if(index-delt>=0&&s[index-delt]==s[index])
15                 doublestring[index-1]=1;
16             if(index+delt<n&&s[index+delt]==s[index])
17                 doublestring[index]=1;
18             while(index-delt>=0&&index+delt<n){
19                 if(s[index-delt]==s[index+delt])
20                 {
21                     if(delt*2+1>maxlen)
22                     {
23                         maxlen=delt*2+1;
24                         maxindex=index;
25                     }
26                     delt++;
27                 }
28                 else
29                     break;
30             }
31         }
32         int resa=maxlen;
33 
34 
35         for(int i=0;i<n;i++)
36         {
37             if(doublestring[i]!=0)
38             {
39                 int index1=i;
40                 int index2=i+1;
41                 int delt=0;
42                 while(index1-delt>=0&&index2+delt<n){
43                     if(s[index1-delt]==s[index2+delt])
44                     {
45                         if(delt*2+2>maxlen)
46                         {
47                             maxlen=delt*2+2;
48                             maxindex=index1;
49                         }
50                         delt++;
51                     }
52                     else
53                         break;
54                 }
55             }
56         }
57         if(maxlen==resa)
58         {
59             int start=maxindex-(maxlen-1)/2;
60             resstring.append(s,start,maxlen);
61         }
62         else
63         {
64             int start=maxindex-(maxlen-2)/2;
65             resstring.append(s,start,maxlen);
66         }
67         //cout<<resstring<<endl;
68         return resstring;
69     }
70 };

这个方法有几个需要注意的地方:

1.对于字符数目为1的字符,直接返回不需进行处理。

2.在第一遍寻找奇数回文的时候,delt为1时不要在循环里面判断是否有对称的结构,如果在里面对于“abb”这种样例就无法通过

3.在第二遍寻找偶数回文的时候,delt应该从0开始,而非从1开始,这样才能判断出“bb”的样例。

4.C++的string字符串的append函数好方便,起始位置start,长度n给出,可以直接复制。

 

以上是我做这个题目的方法,我估计这个题目可以用动态规划解决,想了一会未果。动态规划真是脑力活,自己做的动规也比较少。

http://blog.csdn.net/feliciafay/article/details/16984031

这里有一篇介绍这个问题动态规划解法,至于他提到的O(n)方法。。不敢细看。

另外关于最长回文字串流行的解法是使用后缀树这个数据结构来做。

关于后缀树应用在这个问题的介绍附一个靠谱链接:

http://blog.csdn.net/g9yuayon/article/details/2574781

大致思路是使用后缀树然后找LCA(最近公共祖先),我估计把这个搞明白也要一会,还是继续先刷题吧。

里面还提到了graphviz这个画图工具,好像比visio画程序图更好用的样子。

http://www.graphviz.org/

随意看了看这方面的介绍,发现用这个Drawing graphs with dot文档入门比较靠谱。

 

posted on 2015-07-06 14:30  holyprince  阅读(213)  评论(0编辑  收藏  举报

导航