zoukankan      html  css  js  c++  java
  • Careercup

    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 }
  • 相关阅读:
    hdu4276 依赖背包
    poj1155 依赖背包
    cf219d 基础换根法
    贪婪大陆——(树状数组)
    数星星(树状数组或者线段树)
    拓扑排序基础题——排序
    Codeforces Round #511 (Div. 1) T2 Little C Loves 3 II
    除虫药水(简单dp)
    烽火传递(单调队列优化dp,然而蒟蒻用一个优先队列做)
    ZOJ----3471Most powerful(简单状压dp)
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3703694.html
Copyright © 2011-2022 走看看