Submission #243450

#TimeUsernameProblemLanguageResultExecution timeMemory
243450dolphingarlicNecklace (Subtask 1-3) (BOI19_necklace1)C++14
85 / 85
279 ms106264 KiB
/*
Baltic 2019 Necklace
- Firstly, assume WLOG that we can't flip the necklace.
    - If we do flip it in the optimal solution, just reverse B and run the
      same solution again
- Notice how we'll have A = ...XY... and B = ...YX... where X and Y are substrings
- lcs[i][j] = Longest common suffix of A[:i] and B[:j]
            = lcs[i - 1][j - 1] + 1 if A[i] == B[j] else 0
- dp1[i][j] = Longest suffix of A[:i] that's also a prefix of B[j:]
    - First, dp1[i][j - lcs[i][j]] = max(dp1[i][j - lcs[i][j]], lcs[i][j])
    - Next, dp1[i][j] = max(dp1[i][j], dp1[i][j - 1] - 1)
- dp2[i][j] = Longest prefix of A[i:] that's also a suffix of B[:j]
    - We compute this similarly
- To get this down to O(N) memory, notice how dp[i] only depends on lcs[i]
  and lcs[i] only depends on lcs[i - 1]
- Complexity: O(N^2) with O(N) memory
*/

#include <bits/stdc++.h>
#define FOR(i, x, y) for (int i = x; i < y; i++)
typedef long long ll;
using namespace std;

int lcs[3001][3001], dp1[3001][3001], dp2[3001][3001];
int mx_len, best_i, best_j;

void solve(string A, string B, bool reversed) {
    memset(lcs, 0, sizeof lcs);
    memset(dp1, 0, sizeof dp1);
    memset(dp2, 0, sizeof dp2);
    FOR(i, 1, A.size() - 1) {
        FOR(j, 1, B.size() - 1) {
            lcs[i][j] = (A[i] == B[j] ? lcs[i - 1][j - 1] + 1 : 0);
            dp1[i][j - lcs[i][j]] = max(dp1[i][j - lcs[i][j]], lcs[i][j]);
            dp2[i - lcs[i][j]][j] = max(dp2[i - lcs[i][j]][j], lcs[i][j]);
        }
    }
    FOR(i, 1, A.size() - 1) {
        FOR(j, 1, B.size() - 1) {
            dp1[i][j] = max(dp1[i][j], dp1[i][j - 1] - 1);
            dp2[i][j] = max(dp2[i][j], dp2[i - 1][j] - 1);

            if (dp1[i][j] + dp2[i][j] > mx_len) {
                mx_len = dp1[i][j] + dp2[i][j];
                best_i = i - dp1[i][j];
                if (!reversed) best_j = j - dp2[i][j];
                else best_j = B.size() - j - dp1[i][j] - 2;
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    string A, B;
    cin >> A >> B;
    A = "." + A + ".", B = "." + B + ".";
    solve(A, B, 0);
    reverse(B.begin(), B.end());
    solve(A, B, 1);
    cout << mx_len << '\n' << best_i << ' ' << best_j;
    return 0;
}

Compilation message (stderr)

necklace.cpp: In function 'void solve(std::__cxx11::string, std::__cxx11::string, bool)':
necklace.cpp:20:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
necklace.cpp:31:9:
     FOR(i, 1, A.size() - 1) {
         ~~~~~~~~~~~~~~~~~~              
necklace.cpp:31:5: note: in expansion of macro 'FOR'
     FOR(i, 1, A.size() - 1) {
     ^~~
necklace.cpp:20:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
necklace.cpp:32:13:
         FOR(j, 1, B.size() - 1) {
             ~~~~~~~~~~~~~~~~~~          
necklace.cpp:32:9: note: in expansion of macro 'FOR'
         FOR(j, 1, B.size() - 1) {
         ^~~
necklace.cpp:20:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
necklace.cpp:38:9:
     FOR(i, 1, A.size() - 1) {
         ~~~~~~~~~~~~~~~~~~              
necklace.cpp:38:5: note: in expansion of macro 'FOR'
     FOR(i, 1, A.size() - 1) {
     ^~~
necklace.cpp:20:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
necklace.cpp:39:13:
         FOR(j, 1, B.size() - 1) {
             ~~~~~~~~~~~~~~~~~~          
necklace.cpp:39:9: note: in expansion of macro 'FOR'
         FOR(j, 1, B.size() - 1) {
         ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...