Skip to content

Commit

Permalink
chore: added comments and changed variable name in hard day 6 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
ashutosh-3474 committed Apr 13, 2024
1 parent f603e98 commit 8608b64
Showing 1 changed file with 100 additions and 85 deletions.
185 changes: 100 additions & 85 deletions hard/day_6/solution.cpp
Original file line number Diff line number Diff line change
@@ -1,92 +1,107 @@
//Write your code here
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=a;i<=b;i++)
char l[1010],r[1010];
int ct,c[20000][10],fa[20000],s[17000][2010],n,f[2005][17000],ok[2005][17000],l1,l2;
int nt(int x,int y){
return !c[x][y]?c[x][y]=++ct:c[x][y];
#define fo(i,a,b) for(int i=a;i<=b;i++) // Macro for looping from a to b

char leftString[1010], rightString[1010]; // Arrays for storing left and right strings
int stateCount, transitions[20000][10], suffixLinks[20000], prefixSums[17000][2010], length, n, dp[2005][17000], reachable[2005][17000], leftLength, rightLength; // Variables for counting, storing transitions, and dynamic programming

int newState(int x, int y){
return !transitions[x][y] ? transitions[x][y] = ++stateCount : transitions[x][y]; // Function to get or create a new state
}
void ins(){
l1=strlen(l+1),l2=strlen(r+1);
int x=0,y=0;
if(l1==l2){
fo(i,1,l1){
if(x==y){
fo(j,l[i]-'0'+1,r[i]-'0'-1)
s[nt(x,j)][l1-i]++;
x=nt(x,l[i]-'0');
y=nt(y,r[i]-'0');
}
else{
fo(j,l[i]-'0'+1,9)
s[nt(x,j)][l1-i]++;
x=nt(x,l[i]-'0');
fo(j,(i==1),r[i]-'0'-1)
s[nt(y,j)][l2-i]++;
y=nt(y,r[i]-'0');
}
}
s[x][0]++;
if(x!=y)s[y][0]++;
}
else{
fo(i,1,l1){
fo(j,l[i]-'0'+1,9)
s[nt(x,j)][l1-i]++;
x=nt(x,l[i]-'0');
}
fo(i,1,l2){
fo(j,(i==1),r[i]-'0'-1)
s[nt(y,j)][l2-i]++;
y=nt(y,r[i]-'0');
}
fo(i,l1+1,l2-1)fo(j,1,9)
s[nt(0,j)][i-1]++;
s[x][0]++;
s[y][0]++;
}

void insertStrings(){
leftLength = strlen(leftString + 1), rightLength = strlen(rightString + 1); // Get the lengths of left and right strings
int x = 0, y = 0; // Initialize states for left and right strings
if(leftLength == rightLength){ // If lengths are equal
fo(i, 1, leftLength){
if(x == y){
fo(j, leftString[i] - '0' + 1, rightString[i] - '0' - 1)
prefixSums[newState(x, j)][leftLength - i]++; // Increment count for transitions
x = newState(x, leftString[i] - '0'); // Transition to next state
y = newState(y, rightString[i] - '0'); // Transition to next state
}
else{
fo(j, leftString[i] - '0' + 1, 9)
prefixSums[newState(x, j)][leftLength - i]++; // Increment count for transitions
x = newState(x, leftString[i] - '0'); // Transition to next state
fo(j, (i == 1), rightString[i] - '0' - 1)
prefixSums[newState(y, j)][rightLength - i]++; // Increment count for transitions
y = newState(y, rightString[i] - '0'); // Transition to next state
}
}
prefixSums[x][0]++; // Increment count for final state
if(x != y) prefixSums[y][0]++; // Increment count for final state
}
else{
fo(i, 1, leftLength){
fo(j, leftString[i] - '0' + 1, 9)
prefixSums[newState(x, j)][leftLength - i]++; // Increment count for transitions
x = newState(x, leftString[i] - '0'); // Transition to next state
}
fo(i, 1, rightLength){
fo(j, (i == 1), rightString[i] - '0' - 1)
prefixSums[newState(y, j)][rightLength - i]++; // Increment count for transitions
y = newState(y, rightString[i] - '0'); // Transition to next state
}
fo(i, leftLength + 1, rightLength - 1)
fo(j, 1, 9)
prefixSums[newState(0, j)][i - 1]++; // Increment count for transitions
prefixSums[x][0]++; // Increment count for final state
prefixSums[y][0]++; // Increment count for final state
}
}
queue<int>q;
void bd(){
fo(i,0,9)if(c[0][i])
q.push(c[0][i]);
while(!q.empty()){
int x=q.front();
q.pop();
fo(i,0,l2-1)s[x][i]+=s[fa[x]][i];
fo(i,0,9){
if(c[x][i]){
q.push(c[x][i]);
fa[c[x][i]]=c[fa[x]][i];
}
else c[x][i]=c[fa[x]][i];
}
}
fo(i,0,ct)fo(j,1,n)
s[i][j]+=s[i][j-1];

queue<int> bfsQueue; // Queue for BFS

void buildAutomaton(){
fo(i, 0, 9) if(transitions[0][i])
bfsQueue.push(transitions[0][i]); // Push initial states to the queue
while(!bfsQueue.empty()){
int currentState = bfsQueue.front();
bfsQueue.pop();
fo(i, 0, rightLength - 1)
prefixSums[currentState][i] += prefixSums[suffixLinks[currentState]][i]; // Update counts using suffix link
fo(i, 0, 9){
if(transitions[currentState][i]){
bfsQueue.push(transitions[currentState][i]);
suffixLinks[transitions[currentState][i]] = transitions[suffixLinks[currentState]][i]; // Set suffix link
}
else transitions[currentState][i] = transitions[suffixLinks[currentState]][i]; // Set transition
}
}
fo(i, 0, stateCount)
fo(j, 1, n)
prefixSums[i][j] += prefixSums[i][j - 1]; // Compute prefix sums
}

int main(){
scanf("%s%s%d",l+1,r+1,&n);
ins();
bd();
memset(f,-32,sizeof(f));
f[0][0]=0;
fo(i,0,n-1)fo(j,0,ct)if(f[i][j]>=0)
fo(k,0,9)f[i+1][c[j][k]]=max(f[i+1][c[j][k]],f[i][j]+s[c[j][k]][n-i-1]);
int r=-1e9;
fo(i,0,ct)r=max(r,f[n][i]);
printf("%d\n",r);
fo(i,0,ct)ok[n][i]=(r==f[n][i]);
for(int i=n-1;i;i--)
fo(j,0,ct)fo(k,0,9)
ok[i][j]|=ok[i+1][c[j][k]]&&(f[i+1][c[j][k]]==f[i][j]+s[c[j][k]][n-i-1]);
int x=0;
fo(i,1,n)fo(k,0,9)
if(ok[i][c[x][k]]&&f[i][c[x][k]]==f[i-1][x]+s[c[x][k]][n-i]){
printf("%d",k);
x=c[x][k];
break;
}
scanf("%s%s%d", leftString + 1, rightString + 1, &n); // Input left, right strings, and n
insertStrings(); // Construct automaton
buildAutomaton(); // Build automaton
memset(dp, -32, sizeof(dp)); // Initialize DP table
dp[0][0] = 0; // Base case
fo(i, 0, n - 1)
fo(j, 0, stateCount)
if(dp[i][j] >= 0)
fo(k, 0, 9)
dp[i + 1][transitions[j][k]] = max(dp[i + 1][transitions[j][k]], dp[i][j] + prefixSums[transitions[j][k]][n - i - 1]); // DP transition
int result = -1e9; // Initialize result
fo(i, 0, stateCount)
result = max(result, dp[n][i]); // Update result
printf("%d\n", result); // Output result

fo(i, 0, stateCount)
reachable[n][i] = (result == dp[n][i]); // Mark states achieving the result
for(int i = n - 1; i; i--)
fo(j, 0, stateCount)
fo(k, 0, 9)
reachable[i][j] |= reachable[i + 1][transitions[j][k]] && (dp[i + 1][transitions[j][k]] == dp[i][j] + prefixSums[transitions[j][k]][n - i - 1]); // Mark states for next iteration
int currentState = 0; // Initialize state
fo(i, 1, n)
fo(k, 0, 9)
if(reachable[i][transitions[currentState][k]] && dp[i][transitions[currentState][k]] == dp[i - 1][currentState] + prefixSums[transitions[currentState][k]][n - i]){
printf("%d", k); // Output character
currentState = transitions[currentState][k]; // Transition to next state
break;
}
}

0 comments on commit 8608b64

Please sign in to comment.