题意:给一个字符串,求最长回文子串的长度。

 

 

思路:

(1)暴力穷举。O(n^3) -----绝对不行。

    穷举所有可能的出现子串O(n^2),再判断是否回文O(n)。就是O(n*n*n)了。

 

(2)记录位置。O(n^3) -----绝对不行。

    先扫一遍,记录每个字符在上一次出现的位置pos。每次考虑第i个字符,如果回文子串包括 i 的话,那么肯定在i的前面有一个跟第i个字符是一样的,利用之前记录的位置pos[i]可以找到与第i个相同的字符,如果i-pos[i]比之前发现的最长的子串max还短,那么不用比较了。如果更前面还有和第i个字符一样的,那么可以找到第pos[pos[i]]个,一定要找到区间比max还大的,才有比较的意义,除非前面已经没有相同字符的了。那么略过第i个,直奔下一个。记录位置需要O(n),考虑每个字符需要O(n),对其前面出现过的每个字符考虑O(n),一旦考虑就需要比较是否回文O(n),总的来说,后面3个是乘的关系O(n^3)。

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <vector>
 4 #include <stdio.h>
 5 
 6 using namespace std;
 7 const int N=1000010;
 8 
 9 char str[N];
10 char has[256];
11 char pos[N];
12 
13 
14 bool isP(int j,int i)
15 {
16     while( j!=i && j!=--i)
17     {
18         if( str[j]!=str[i] )
19             return false;
20         j++;
21     }
22     return true;
23 }
24 
25 int fin_ex(int max, int i)
26 {
27     int j=pos[i];
28     while( i-j<=max && j>-1 )      //找到一个区间范围大于max的,开始算
29         j=pos[j];
30     return j;
31 }
32 
33 int cal(int len)
34 {
35     int max=1, j;
36     for(int i=0; i<len; i++)
37     {
38         j=fin_ex(max, i);      //找相同的,且大于max的
39         while( j!=-1 && i-j>max )    //有相同
40         {
41             if(isP(j,i+1)==true)
42                 max=i-j+1;
43             else
44                 j=fin_ex(max, j); //不是回文,继续找
45         }
46     }
47     return max;
48 }
49 
50 
51 int main()
52 {
53     //freopen("input.txt", "r", stdin);
54     int t;
55     cin>>t;
56     getchar();
57     while(t--)
58     {
59         gets(str);
60         int len=strlen(str);
61         for(int i=0; i<256; i++)    has[i]=-1;      //初始化
62         for(int i=0; i<len; i++)                    //记录上一次出现的位置
63         {
64             pos[i]=has[str[i]];
65             has[str[i]]=i;
66         }
67 
68         cout<<cal(len)<<endl;
69     }
70     return 0;
71 }
TLE代码

相关文章: