Problem:
Score : 1100 points

Problem Statement

Given is a string S consisting of 0 and 1. Find the number of strings, modulo 998244353, that can result from applying the following operation on S zero or more times:

Remove the two characters at the beginning of S, erase one of them, and reinsert the other somewhere in S. This operation can be applied only when S has two or more characters.

Constraints

1 \leq |S| \leq 300

S consists of 0 and 1.

Input

Input is given from Standard Input in the following format:

S

Output

Print the number of strings, modulo 998244353, that can result from applying the operation on S zero or more times.

Sample Input 1

0001

Sample Output 1

8

Eight strings, 0001, 001, 010, 00, 01, 10, 0, and 1, can result.

Sample Input 2

110001

Sample Output 2

24

Sample Input 3

11101111011111000000000110000001111100011111000000001111111110000000111111111

Sample Output 3

697354558

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <chrono>
#include <random>
#include <cassert>
#include <cstring>

std::mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count());

const int ms = 303;
const int MOD = 998244353;

std::string str;
int n;
bool vis[ms][ms][ms];
int memo[ms][ms][ms];
int bst[ms][ms];
int sum[ms][2];

void go(int on, int zero, int one, int turn) {
	if(vis[on][zero][turn]) return;
	vis[on][zero][turn] = true;
	//std::cout << "visiting " << on << ", " << zero << ", " << one << ", " << turn << "\n";
	memo[on][zero][turn] = one;
	if(turn + 1 == (int) str.size()) return;
	if(zero >= 2) go(on, zero-1, one, turn+1);
	if(one >= 2) go(on, zero, one-1, turn+1);
	if(zero >= 1 && one >= 1) go(on, zero-1, one, turn+1);
	if(zero >= 1 && one >= 1) go(on, zero, one-1, turn+1);
	if(on < (int) str.size()) {
		int nxt = str[on] - '0';
		if(zero >= 1) go(on+1, zero-1+(1-nxt), one+nxt, turn+1);
		if(one >= 1) go(on+1, zero+(1-nxt), one+nxt-1, turn+1);
		if(zero >= 1 || one >= 1) go(on+1, zero, one, turn+1);
	}
	if(on+1 < (int) str.size()) {
		int nxt = str[on] - '0';
		go(on+2, zero+(1-nxt), one+nxt, turn+1);
		nxt = str[on+1] - '0';
		go(on+2, zero+(1-nxt), one+nxt, turn+1);
	}
}

int dp(int on, int zero, int one) {
	if(zero < 0 || one < 0) return 0;
	if(on == n && zero == 0 && one == 0) return 1;
	int &ans = memo[on][zero][one];
	if(ans != -1) return ans;
	ans = 0;
	if(on == n) {
		ans = (dp(on, zero-1, one) + dp(on, zero, one-1)) % MOD;
	} else if(str[on] == '0') {
		ans = (dp(on+1, zero, one) + dp(on, zero, one-1)) % MOD;
	} else {
		ans = (dp(on+1, zero, one) + dp(on, zero-1, one)) % MOD;
	}
	return ans;
}

int main() {
	std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);
	std::cin >> str;
	n = (int) str.size();
	go(0, 0, 0, 0);
	for(int i = n-1; i >= 0; i--) {
		sum[i][0] = sum[i+1][0];
		sum[i][1] = sum[i+1][1];
		if(str[i] == '0') sum[i][0]++;
		else sum[i][1]++;
	}
	memset(bst, -1, sizeof bst);
	for(int on = 0; on < ms; on++) {
		for(int zero = 0; zero < ms; zero++) {
			for(int turn = 0; turn < ms; turn++) {
				if(!vis[on][zero][turn]) continue;
				int one = memo[on][zero][turn];
				int f[2] = {zero + sum[on][0], one + sum[on][1]};
				bst[f[0]][f[1]] = std::max(bst[f[0]][f[1]], on);
			}
		}
	}
	memset(memo, -1, sizeof memo);
	int ans = 0;
	for(int zero = 0; zero < ms; zero++) {
		for(int one = 0; one < ms; one++) {
			if(bst[zero][one] < 0) continue;
			int on = bst[zero][one];
			//std::cout << "best for " << zero << ", " << one << " is " << on << ", got " << dp(on, zero - sum[on][0], one - sum[on][1]) << '\n';
			ans = (ans + dp(on, zero - sum[on][0], one - sum[on][1])) % MOD;
		}
	}
	std::cout << ans << '\n';
}