제출 #1248509

#제출 시각아이디문제언어결과실행 시간메모리
1248509avighnaCopy and Paste 3 (JOI22_copypaste3)C++20
100 / 100
2264 ms318496 KiB
#include <bits/stdc++.h>

const int64_t A1 = 43, A2 = 31;
const int64_t mod1 = 1e9 + 7, mod2 = 1000139249;
std::vector<int64_t> pow1, pow2;
const int64_t inf = 1e15;

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int n;
  std::string s;
  int a, b, c;
  std::cin >> n >> s >> a >> b >> c;

  pow1.resize(n), pow2.resize(n);
  pow1[0] = pow2[0] = 1;
  for (int i = 1; i < n; ++i) {
    pow1[i] = (pow1[i - 1] * A1) % mod1;
    pow2[i] = (pow2[i - 1] * A2) % mod2;
  }
  struct Hash {
    int64_t hash1, hash2, len;
    Hash() : hash1(0), hash2(0), len(0) {}
    Hash(int64_t hash1, int64_t hash2, int64_t len) : hash1(hash1), hash2(hash2), len(len) {}
    bool operator<(const Hash &other) const {
      if (len != other.len) {
        return len < other.len;
      }
      if (hash1 != other.hash1) {
        return hash1 < other.hash1;
      }
      return hash2 < other.hash2;
    }
    bool operator==(const Hash &other) const {
      return hash1 == other.hash1 and hash2 == other.hash2 and len == other.len;
    }
    void append(char c) {
      hash1 = (hash1 + pow1[len] * c) % mod1;
      hash2 = (hash2 + pow2[len++] * c) % mod2;
    }
  };

  std::vector<Hash> all_hashes;
  for (int i = 0; i < n; ++i) {
    Hash cur_hash;
    for (int j = i; j < n; ++j) {
      cur_hash.append(s[j]);
      all_hashes.push_back(cur_hash);
    }
  }
  std::sort(all_hashes.begin(), all_hashes.end());
  all_hashes.erase(std::unique(all_hashes.begin(), all_hashes.end()), all_hashes.end());
  std::vector hashes(n, std::vector<int>(n + 1));
  std::vector<std::vector<int>> positions(all_hashes.size());
  for (int i = 0; i < n; ++i) {
    Hash cur_hash;
    for (int j = i; j < n; ++j) {
      cur_hash.append(s[j]);
      positions[hashes[i][j + 1] = std::lower_bound(all_hashes.begin(), all_hashes.end(), cur_hash) - all_hashes.begin()].push_back(i);
    }
  }

  std::vector dp(n, std::vector<int64_t>(n + 1, inf));
  for (int i = 0; i < n; ++i) {
    dp[i][i + 1] = a + b;
  }
  for (int64_t len = 1; len <= n; ++len) {
    for (int l = 0; l + len <= n; ++l) {
      int r = l + len;
      if (l > 0) {
        dp[l - 1][r] = std::min(dp[l - 1][r], dp[l][r] + a);
      }
      if (r < n) {
        dp[l][r + 1] = std::min(dp[l][r + 1], dp[l][r] + a);
      }
      if (c > a * len) {
        continue;
      }
      int hash = hashes[l][r];
      auto it = std::lower_bound(positions[hash].begin(), positions[hash].end(), l);
      int64_t cnt = 1;
      while (it != positions[hash].end() and *it + len <= n) {
        dp[l][*it + len] = std::min(dp[l][*it + len], dp[l][r] + cnt * c + (*it + len - l - len * cnt) * a + b);
        it = std::lower_bound(positions[hash].begin(), positions[hash].end(), *it + len);
        cnt += 1;
      }
    }
  }

  std::cout << dp[0][n] - b << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...