2014-05-02 08:29

题目链接

原题:

Write a function for retrieving the total number of substring palindromes. 
For example the input is 'abba' then the possible palindromes= a, b, b, a, bb, abba 
So the result is 6. 

Updated at 11/11/2013: 
After the interview I got know that the O(n^3) solution is not enough to go to the next round. It would have been better to know before starting implementing the solution unnecessarily ...

题目:给定一个字符串,统计所有回文子串的个数。O(n^3)的算法是明显的暴力算法,当然要被淘汰了。

解法1:一个简单的优化,是O(n^2)的。从每个位置向两边计算有多少个回文串。这样可以用O(1)空间,O(n^2)时间完成算法。

代码:

 1 // http://www.careercup.com/question?id=5177378863054848
 2 #include <iostream>
 3 #include <string>
 4 #include <vector>
 5 using namespace std;
 6 
 7 int countPalindrome(const string &s)
 8 {
 9     int n = (int)s.length();
10     if (n <= 1) {
11         return n;
12     }
13     
14     int i, j;
15     int res;
16     int count;
17     
18     res = 0;
19     for (i = 0; i < n; ++i) {
20         j = 0;
21         count = 0;
22         while (i - j >= 0 && i + j <= n - 1 && s[i - j] == s[i + j]) {
23             ++count;
24             ++j;
25         }
26         res += count;
27         
28         j = 0;
29         count = 0;
30         while (i - j >= 0 && i + 1 + j <= n - 1 && s[i - j] == s[i + 1 + j]) {
31             ++count;
32             ++j;
33         }
34         res += count;
35     }
36     
37     return res;
38 }
39 
40 int main()
41 {
42     string s;
43 
44     while(cin >> s) {
45         cout << countPalindrome(s) << endl;
46     }
47 
48     return 0;
49 }

解法2:有个很巧妙的回文串判定算法,叫Manacher算法,可以在O(n)时间内找出最长回文字串的长度。这题虽然是统计个数,同样可以用Manacher算法搞定。Manacher算法中有个很重要的概念,叫“最长回文匹配半径”,意思是当前最长回文子串能覆盖到的最靠右的位置。每当我们检查的中心位置处于这个半径之内时,就可以和另一边的对称点进行参照,减少一些重复的扫描。如果处于半径之外,就按照常规的方式向两边扫描了。Manacher算法的思想一两句话很难说清楚,在此提供一个链接吧:Manacher算法处理字符串回文

代码:

  1 // http://www.careercup.com/question?id=5177378863054848
  2 // Modified Manacher Algorithm
  3 #include <algorithm>
  4 #include <ctime>
  5 #include <iostream>
  6 #include <string>
  7 #include <vector>
  8 using namespace std;
  9 
 10 class Solution {
 11 public:
 12     long long int countPalindrome(const string &s) {
 13         int n = (int)s.length();
 14         
 15         if (n <= 1) {
 16             return n;
 17         }
 18         
 19         preProcess(s);
 20         n = (int)ss.length();
 21         int far;
 22         int far_i;
 23         
 24         int i;
 25 
 26         far = 0;
 27         c[0] = 0;
 28         for (i = 1; i < n; ++i) {
 29             c[i] = 1;
 30             if (far > i) {
 31                 c[i] = c[2 * far_i - i];
 32                 if (far - i < c[i]) {
 33                     c[i] = far - i;
 34                 }
 35             }
 36             
 37             while (ss[i - c[i]] == ss[i + c[i]]) {
 38                 ++c[i];
 39             }
 40             
 41             if (i + c[i] > far) {
 42                 far = i + c[i];
 43                 far_i = i;
 44             }
 45         }
 46         
 47         long long int count = 0;
 48         for (i = 0; i < n; ++i) {
 49             count += (c[i] + (i & 1)) / 2;
 50         }
 51         
 52         ss.clear();
 53         c.clear();
 54         
 55         return count;
 56     }
 57 private:
 58     string ss;
 59     vector<int> c;
 60     
 61     void preProcess(const string &s) {
 62         int n;
 63         int i;
 64         
 65         n = (int)s.length();
 66         ss.clear();
 67         // don't insert '#' here, index may go out of bound.
 68         ss.push_back('$');
 69         for (i = 0; i < n; ++i) {
 70             ss.push_back(s[i]);
 71             ss.push_back('#');
 72         }
 73         c.resize(ss.length());
 74     };
 75 };
 76 
 77 int main()
 78 {
 79     string s;
 80     Solution sol;
 81     const int big_n = 500000;
 82 
 83     s.resize(big_n);
 84     for(int i = 0; i < big_n; ++i) {
 85         s[i] = 'a';
 86     }
 87     
 88     clock_t start, end;
 89     start = clock();
 90     cout << sol.countPalindrome(s) << endl;
 91     end = clock();
 92     cout << "Runtime for test case of size " << big_n << ": " 
 93          << (1.0 * (end - start) / CLOCKS_PER_SEC) 
 94          << " seconds." << endl;
 95 
 96     while (cin >> s) {
 97         cout << sol.countPalindrome(s) << endl;
 98     }
 99     
100     return 0;
101 }

 

 posted on 2014-05-02 09:33  zhuli19901106  阅读(220)  评论(0编辑  收藏  举报