Z_Michael

1635

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