Z_Michael

1635_2

Apr 22nd, 2020
363
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.30 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <algorithm>
  5. using namespace std;
  6.  
  7. string s;
  8.  
  9. long long n = 4010, p, m = 5000007;
  10.  
  11. vector <unsigned long long> paw(n), h(n), rh(n), evenCount(n), oddCount(n), r({ 10000, 0 });
  12. vector <vector <unsigned long long>> dp(n, r);
  13.  
  14. auto getHash(int L, int R) {
  15.     auto result = h[R];
  16.     if (L > 0) result -= h[L - 1];
  17.     return result;
  18. }
  19.  
  20. auto getRevHash(int L, int R) {
  21.     auto result = rh[L];
  22.     if (R < n - 1) result -= rh[R + 1];
  23.     return result;
  24. }
  25.  
  26. void rek(int prev, int tek) {
  27.     if (tek != 0) {
  28.         rek(tek, dp[tek][1]);
  29.     }
  30.  
  31.     for (int i = tek; i < prev; i++) {
  32.         cout << s[i];
  33.     }
  34.  
  35.     cout << " ";
  36. }
  37.  
  38. bool isPalindrome(int L, int R) {
  39.     return (getHash(L, R) * paw[n - R - 1]) % m == (getRevHash(L, R) * paw[L]) % m;
  40. }
  41.  
  42. int main()
  43. {
  44.     iostream::sync_with_stdio(false);
  45.     cin.tie(0), cout.tie(0);
  46.  
  47.     cin >> s;
  48.     n = s.size(), p = 239017;
  49.  
  50.  
  51.  
  52.     paw[0] = 1;
  53.     for (int i = 1; i < n; i++) {
  54.         paw[i] = (paw[i - 1] * p) % m;
  55.     }
  56.  
  57.     h[0] = s[0];
  58.     for (int i = 1; i < n; i++) {
  59.         h[i] = h[i - 1] + (paw[i] * s[i]) % m;
  60.     }
  61.  
  62.     rh[n - 1] = s[n - 1];
  63.     for (int i = n - 2, j = 1; i >= 0; i--, j++) {
  64.         rh[i] = rh[i + 1] + (paw[j] * s[i]) % m;
  65.     }
  66.  
  67.     for (long long i = 0; i < (n - 1); i++) {
  68.         int left = 0, right = min(i + 1, n - i - 1);
  69.         while (left < right) {
  70.             int middle = (left + right) / 2;
  71.             if (isPalindrome(i - middle, i + middle + 1)) {
  72.                 evenCount[i] = middle + 1;
  73.                 left = middle + 1;
  74.             }
  75.             else {
  76.                 right = middle;
  77.             }
  78.         }
  79.     }
  80.  
  81.     for (long long i = 0; i < n; i++) {
  82.         int left = 0, right = min(i + 1, n - i);
  83.         while (left < right) {
  84.             int middle = (left + right) / 2;
  85.             if (isPalindrome(i - middle, i + middle)) {
  86.                 oddCount[i] = middle;
  87.                 left = middle + 1;
  88.             }
  89.             else {
  90.                 right = middle;
  91.             }
  92.         }
  93.     }
  94.  
  95.     dp[0][0] = 0;
  96.     dp[0][1] = 0;
  97.     dp[1][0] = 1;
  98.     dp[1][1] = 0;
  99.  
  100.     for (int i = 1; i <= n; i++) {
  101.         for (int j = 1; j <= evenCount[i - 1]; j++) {
  102.             if (dp[i - j][0] + 1 < dp[i + j][0]) {
  103.                 dp[i + j][0] = dp[i - j][0] + 1;
  104.                 dp[i + j][1] = i - j;
  105.             }
  106.  
  107.         }
  108.  
  109.         for (int j = 0; j <= oddCount[i - 1]; j++) {
  110.             if (dp[i - j - 1][0] + 1 < dp[i + j][0]) {
  111.                 dp[i + j][0] = dp[i - j - 1][0] + 1;
  112.                 dp[i + j][1] = i - j - 1;
  113.             }
  114.         }
  115.  
  116.     }
  117.  
  118.     cout << dp[n][0] << "\n";
  119.     rek(n, n);
  120. }
Advertisement
Add Comment
Please, Sign In to add comment