Two Strings Game – HackerRank Solution

In this post, we will solve Two Strings Game HackerRank Solution. This problem (Two Strings Game) is a part of HackerRank Problem Solving series.

Contents

Solution – Two Strings Game – HackerRank Solution

C++

```#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;

#define maxn 300000
#define limit 1000000000000000000LL

long long k;

int n, m, i, j, cur, bad_value, kk;
char a[maxn], b[maxn];
bool was[30];
pair<int, int> srt[maxn * 2 + 3];

struct sfa {

long long dp[maxn * 2 + 3], grundy_sum[30], ways[maxn * 2 + 3];

int next[maxn * 2 + 3][26], len[maxn * 2 + 3], lnk[maxn * 2 + 3], grundy[maxn * 2 + 3];
int nodes, last, j;

void init () {
nodes = last = 1;
len[1] = lnk[1] = 0;
}

void push (int c) {
int cur = ++nodes, p;
len[cur] = len[last] + 1;
for(p = last; p && !next[p][c]; p = lnk[p]) next[p][c] = cur;
if (!p) lnk[cur] = 1; else {
int q = next[p][c];
if (len[p] + 1 == len[q]) lnk[cur] = q; else {
int clone = ++nodes;
len[clone] = len[p] + 1;
for(int j = 0; j < 26; j++) next[clone][j] = next[q][j];
lnk[clone] = lnk[q];
for(; p && next[p][c] == q; p = lnk[p]) next[p][c] = clone;
lnk[q] = lnk[cur] = clone;
}
}
last = cur;
}

void grundy_precalc () {
for(i = 1; i <= nodes; i++) srt[i] = make_pair(len[i], i);
sort(srt + 1, srt + nodes + 1);
for(i = 1; i <= nodes; i++) {
int k = srt[nodes - i + 1].second;
dp[k] = 1;
for(j = 0; j < 30; j++) was[j] = 0;
for(j = 0; j < 26; j++) if (next[k][j]) was[grundy[next[k][j]]] = true;
for(j = 0; j < 30; j++) if (!was[j]) {
grundy[k] = j;
break;
}
}
}

void substr_precalc () {
for(i = 1; i <= nodes; i++) srt[i] = make_pair(len[i], i);
sort(srt + 1, srt + nodes + 1);
for(i = 1; i <= nodes; i++) {
int k = srt[nodes - i + 1].second;
dp[k] = 1;
for(j = 0; j < 26; j++) if (next[k][j]) dp[k] += dp[next[k][j]];
}
ways[1] = 1;
for(i = 1; i <= nodes; i++) for(j = 0; j < 26; j++) if (next[srt[i].second][j]) ways[next[srt[i].second][j]] += ways[srt[i].second];
for(i = 1; i <= nodes; i++) grundy_sum[grundy[i]] += ways[i];
}

void dp_recalc (int bad_value) {
for(i = 1; i <= nodes; i++) srt[i] = make_pair(len[i], i);
sort(srt + 1, srt + nodes + 1);
for(i = 1; i <= nodes; i++) {
int k = srt[nodes - i + 1].second;
dp[k] = grundy[k] != bad_value;
for(j = 0; j < 26; j++) if (next[k][j]) dp[k] += dp[next[k][j]];
}
}

} sfa1, sfa2;

int main (int argc, char * const argv[]) {
//    freopen("input.txt", "r", stdin);
scanf("%d %d %lld\n", &n, &m, &k);

sfa1.init();
sfa2.init();

for(i = 0; i < n; i++) {
a[i] = getchar();
while (a[i] < 'a' || a[i] > 'z') a[i] = getchar();
sfa1.push(a[i] - 'a');
}
for(i = 0; i < m; i++) {
b[i] = getchar();
while (b[i] < 'a' || b[i] > 'z') b[i] = getchar();
sfa2.push(b[i] - 'a');
}

sfa1.grundy_precalc();
for(i = 1; i <= sfa2.nodes; i++) was[i] = false;
sfa2.grundy_precalc();

sfa2.substr_precalc();

for(i = 1; i <= sfa1.nodes; i++) srt[i] = make_pair(sfa1.len[i], i);
sort(srt + 1, srt + sfa1.nodes + 1);
for(i = 1; i <= sfa1.nodes; i++) {
kk = srt[sfa1.nodes - i + 1].second;
sfa1.dp[kk] = sfa2.dp[1] - sfa2.grundy_sum[sfa1.grundy[kk]];
for(j = 0; j < 26; j++) if (sfa1.next[kk][j]) {
sfa1.dp[kk] += sfa1.dp[sfa1.next[kk][j]];
if (sfa1.dp[kk] > limit) sfa1.dp[kk] = limit;
}
}

if (k > sfa1.dp[1]) {
puts("no solution");
return 0;
}

cur = 1;
while (k > 0) {
if (k <= sfa2.dp[1] - sfa2.grundy_sum[sfa1.grundy[cur]]) break; else k -= sfa2.dp[1] - sfa2.grundy_sum[sfa1.grundy[cur]];
for(j = 0; j < 26; j++) if (k > sfa1.dp[sfa1.next[cur][j]]) k -= sfa1.dp[sfa1.next[cur][j]]; else {
putchar('a' + j);
cur = sfa1.next[cur][j];
break;
}
}
puts("");

cur = 1;
while (k > 0) {
if (sfa2.grundy[cur] != bad_value) {
--k;
if (k == 0) break;
}
for(j = 0; j < 26; j++) if (k > sfa2.dp[sfa2.next[cur][j]]) k -= sfa2.dp[sfa2.next[cur][j]]; else {
putchar('a' + j);
cur = sfa2.next[cur][j];
break;
}
}
puts("");
return 0;
}
```

Java

```import java.io.*;
import java.util.*;

public class Solution {

static final int maxn = 300000;
static final long limit = 1000000000000000000l;

static boolean[] was = new boolean[30];
static long[] srt;

static class Sfa {

long[] dp;
long[] grundySum;
long[] ways;

int[][] next;
int[] len;
int[] lnk;
int[] grundy;

int nodes, last;

Sfa(int n) {
dp = new long[maxn * 2 + 3];
grundySum = new long[30];
ways = new long[maxn * 2 + 3];

next = new int[26][maxn * 2 + 3];
len = new int[maxn * 2 + 3];
lnk = new int[maxn * 2 + 3];
grundy = new int[maxn * 2 + 3];

nodes = last = 1;
len[1] = lnk[1] = 0;
}

void push(int c) {
int cur = ++nodes, p;
len[cur] = len[last] + 1;
for (p = last; (p > 0) && (next[c][p] == 0); p = lnk[p]) {
next[c][p] = cur;
}
if (p == 0) {
lnk[cur] = 1;
} else {
int q = next[c][p];
if (len[p] + 1 == len[q]) {
lnk[cur] = q;
} else {
int clone = ++nodes;
len[clone] = len[p] + 1;
for (int j = 0; j < 26; j++) {
next[j][clone] = next[j][q];
}
lnk[clone] = lnk[q];
for (; (p > 0) && next[c][p] == q; p = lnk[p]) {
next[c][p] = clone;
}
lnk[q] = lnk[cur] = clone;
}
}
last = cur;
}

void grundyPrecalc() {
for (int i = 1; i <= nodes; i++) {
srt[i] = ((long)len[i]  << 32l) | i;
}
Arrays.sort(srt, 1, nodes + 1);
for (int i = 1; i <= nodes; i++) {
int k = (int)(srt[nodes - i + 1] & 0xffffffffL);
dp[k] = 1;
Arrays.fill(was, false);
for (int j = 0; j < 26; j++) {
if (next[j][k] > 0) {
was[grundy[next[j][k]]] = true;
}
}
for (int j = 0; j < 30; j++) {
if (!was[j]) {
grundy[k] = j;
break;
}
}
}
}

void substrPrecalc() {
for (int i = 1; i <= nodes; i++) {
srt[i] = ((long)len[i]  << 32l) | i;
}
Arrays.sort(srt, 1, nodes + 1);
for (int i = 1; i <= nodes; i++) {
int k = (int)(srt[nodes - i + 1] & 0xffffffffL);
dp[k] = 1;
for (int j = 0; j < 26; j++) {
if (next[j][k] > 0) {
dp[k] += dp[next[j][k]];
}
}
}
ways[1] = 1;
for (int i = 1; i <= nodes; i++) {
int k = (int)(srt[i] & 0xffffffffL);
for (int j = 0; j < 26; j++) {
if (next[j][k] > 0) {
ways[next[j][k]] += ways[k];
}
}
}
for (int i = 1; i <= nodes; i++) {
grundySum[grundy[i]] += ways[i];
}
}

void dpRecalc(int badValue) {
for (int i = 1; i <= nodes; i++) {
srt[i] = ((long)len[i]  << 32l) | i;
}
Arrays.sort(srt, 1, nodes + 1);
for (int i = 1; i <= nodes; i++) {
int k = (int)(srt[nodes - i + 1] & 0xffffffffL);
dp[k] = grundy[k] != badValue ? 1 : 0;
for (int j = 0; j < 26; j++) {
if (next[j][k] > 0) {
dp[k] += dp[next[j][k]];
}
}
}
}
}

public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
long k = Long.parseLong(st.nextToken());

srt = new long[maxn * 2 + 3];

Sfa sfa1 = new Sfa(n);

char[] a = br.readLine().toCharArray();
for (int i = 0; i < n; i++) {
sfa1.push(a[i] - 'a');
}

Sfa sfa2 = new Sfa(n);

char[] b = br.readLine().toCharArray();
for (int i = 0; i < m; i++) {
sfa2.push(b[i] - 'a');
}

sfa1.grundyPrecalc();
for (int i = 1; i <= (sfa2.nodes > 29 ? 29 : sfa2.nodes); i++) {
was[i] = false;
}

sfa2.grundyPrecalc();
sfa2.substrPrecalc();

for (int i = 1; i <= sfa1.nodes; i++) {
srt[i] = ((long)sfa1.len[i]  << 32l) | i;
}
Arrays.sort(srt, 1, sfa1.nodes + 1);
for (int i = 1; i <= sfa1.nodes; i++) {
int kk = (int)(srt[sfa1.nodes - i + 1] & 0xffffffffL);
sfa1.dp[kk] = sfa2.dp[1] - sfa2.grundySum[sfa1.grundy[kk]];
for (int j = 0; j < 26; j++) {
if (sfa1.next[j][kk] > 0) {
sfa1.dp[kk] += sfa1.dp[sfa1.next[j][kk]];
if (sfa1.dp[kk] > limit) {
sfa1.dp[kk] = limit;
}
}
}
}

if (k > sfa1.dp[1]) {
bw.write("no solution");
bw.newLine();

bw.close();
br.close();
return;
}
int cur = 1;
while (k > 0) {
if (k <= sfa2.dp[1] - sfa2.grundySum[sfa1.grundy[cur]]) {
break;
} else {
k -= sfa2.dp[1] - sfa2.grundySum[sfa1.grundy[cur]];
}
for (int j = 0; j < 26; j++)
if (k > sfa1.dp[sfa1.next[j][cur]])
k -= sfa1.dp[sfa1.next[j][cur]];
else {
bw.write('a' + j);
cur = sfa1.next[j][cur];
break;
}
}
bw.newLine();

int badValue = sfa1.grundy[cur];
cur = 1;
while (k > 0) {
if (sfa2.grundy[cur] != badValue) {
--k;
if (k == 0) {
break;
}
}
for (int j = 0; j < 26; j++) {
if (k > sfa2.dp[sfa2.next[j][cur]]) {
k -= sfa2.dp[sfa2.next[j][cur]];
} else {
bw.write('a' + j);
cur = sfa2.next[j][cur];
break;
}
}
}

bw.newLine();

bw.close();
br.close();
}
}
```

Note: This problem (Two Strings Game) is generated by HackerRank but the solution is provided by CodingBroz. This tutorial is only for Educational and Learning purpose.