# Shashank and the Palindromic Strings

### Problem Statement :

```Shashank loves strings, but he loves palindromic strings the most. He has a list of n strings, A = [a0,a1,...,an-1] , where each string, ai, consists of lowercase English alphabetic letters. Shashank wants to count the number of ways of choosing non-empty subsequences s0,s1,s2,...,sn-1 such that the following conditions are satisfied:

1.s0 is a subsequence of string a0, s1 is a subsequence of string a1, s2 is a subsequence of string a2, ..., and sn-1 is a subsequence of string .
2. s-+s1+s2+ ...+ sn-1 is a palindromic string, where + denotes the string concatenation operator.
You are given q queries where each query consists of some list, A. For each query, find and print the number of ways Shashank can choose n non-empty subsequences satisfying the criteria above, modulo 10^9 + 7, on a new line.

Note: Two subsequences consisting of the same characters are considered to be different if their characters came from different indices in the original string.

Input Format

The first line contains a single integer, q, denoting the number of queries. The subsequent lines describe each query in the following format:

The first line contains an integer, n, denoting the size of the list.
Each line i of the n subsequent lines contains a non-empty string describing ai.
Constraints
1 <= q <= 50
1 <= n <= 50
Σ |ai| <= 1000 over a test case.
For 40% of the maximum score:
1 <= n <= 5
Σ |ai| <= 250 over a test case.
Output Format

For each query, print the number of ways of choosing non-empty subsequences, modulo 10^9 + 7, on a new line.```

### Solution :

```                            ```Solution in C :

In C++ :

#include <bits/stdc++.h>

using namespace std;

#define vec vector
#define ALL(x) (x).begin(), (x).end()
#define mp make_pair
#define mt make_tuple

typedef pair< int, int > pii;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

int const inf = 1000 * 1000 * 1000;
ll const inf64 = 1ll * inf * inf;

int const mod = inf + 7;

inline int sum(int a, int b) { return (a + b) % mod; }
inline int raz(int a, int b) { return ((a - b) % mod + mod) % mod; }
inline int mul(int a, int b) { return (1ll * a * b) % mod; }

bool solve() {

int n;
cin >> n;

vec< string > a(n);
string text = "";

for(int i = 0;i < n;i++) cin >> a[i], text += a[i];

int sz = (int)text.size();

vec< int > id(sz);

for(int j = 0, i = 0;i < n;i++) {
for(int iter = 0;iter < (int)a[i].size();iter++) {
id[j++] = i;
}
}

vec< int > le(n, inf);
vec< int > ri(n,-inf);

for(int i = 0;i < sz;i++) {
le[id[i]] = min(le[id[i]], i);
ri[id[i]] = max(ri[id[i]], i);
}

vec< vec< int > > dp(sz, vec< int >(sz));
vec< vec< int > > sm(sz, vec< int >(sz));

for(int l = sz - 1;l >= 0;l--) {
for(int r = l;r < sz;r++) {
if(r > 0) sm[l][r] = sum(sm[l][r], sm[l][r - 1]);
if(l + 1 < sz) sm[l][r] = sum(sm[l][r], sm[l + 1][r]);
if(r > 0 && l + 1 < sz) sm[l][r] = raz(sm[l][r], sm[l + 1][r - 1]);

if(r < l || text[l] != text[r]) continue;

dp[l][r] = id[r] - id[l] <= 1;

int tl1, tr1, tl2, tr2;

tl1 = l + 1;
tr1 = min(r - 1, id[l] + 1 < n ? ri[id[l] + 1] : ri[id[l]]);

tl2 = max(l + 1, id[r] ? le[id[r] - 1] : le[id[r]]);
tr2 = r - 1;

if(tl1 <= tr1 && tl2 <= tr2) {
dp[l][r] = sum(dp[l][r], sm[tl1][tr2]);
if (tl2 > 0) dp[l][r] = raz(dp[l][r], sm[tl1][tl2 - 1]);
if (tr1 + 1 < sz) dp[l][r] = raz(dp[l][r], sm[tr1 + 1][tr2]);
if (tr1 + 1 < sz && tl2 > 0) dp[l][r] = sum(dp[l][r], sm[tr1 + 1][tl2 - 1]);
}

sm[l][r] = sum(sm[l][r], dp[l][r]);
}
}

int res = 0;

for(int l = 0;l < (int)a[0].size();l++) {
for(int r = sz - 1;r >= l && r >= sz - (int)a[n - 1].size();r--) {
res = sum(res, dp[l][r]);
}
}

cout << res << "\n";

return true;
}

int main() {

int T;
cin >> T;

while(T--) solve();

return 0;
}

In Java :

import java.io.*;
import java.math.*;
import java.text.*;
import java.util.*;
import java.util.regex.*;

public class Solution {
final static int MODE = 1000000007;
/*
* Complete the palindromicStrings function below.
*/
static int palindromicStrings(int[] a, char[] cc) {
final int N = cc.length;
int[][] dp = new int[6*N][N];
int[] ids = new int[N];
int t=a[0]==1?0:1;
for(int i=1;i<N;++i){
if(t==0){
ids[i]=ids[i-1]+1;
}else{
ids[i]=ids[i-1];
}
++t;
if(a[ids[i]]==t)t=0;
}
int[] st = new int[6];
for(int i=1;i<6;++i)st[i]=i*N;
for(int i=N-1;i>=0;--i){
dp[st[5]+i][i]=dp[st[4]+i][i]=dp[i][i]=1;
dp[st[3]+i][i]=dp[st[2]+i][i]=dp[st[1]+i][i]=2;
for(int j=i+1;j<N;++j){
if(ids[j]==ids[j-1]){
dp[st[5]+i][j]=dp[st[5]+i][j-1];
dp[st[4]+i][j]=dp[st[4]+i][j-1];
}else{
dp[st[5]+i][j]=dp[st[4]+i][j-1];
}
if(cc[i]==cc[j]){
if(i+1==j){
++dp[st[5]+i][j];
++dp[st[4]+i][j];
}else{
int k=0;
if(ids[i]==ids[i+1])k+=2;
if(ids[j]==ids[j-1])k+=1;
dp[st[5]+i][j]=(dp[st[5]+i][j]+dp[st[k]+i+1][j-1])%MODE;
dp[st[4]+i][j]=(dp[st[4]+i][j]+dp[st[k]+i+1][j-1])%MODE;
}
}
dp[st[1]+i][j]=dp[st[3]+i][j]=dp[st[5]+i][j];
dp[st[0]+i][j]=dp[st[2]+i][j]=dp[st[4]+i][j];
if(ids[i]==ids[i+1]){
dp[st[3]+i][j]=(dp[st[3]+i][j]+dp[st[3]+i+1][j])%MODE;
dp[st[2]+i][j]=(dp[st[2]+i][j]+dp[st[2]+i+1][j])%MODE;
dp[st[1]+i][j]=(dp[st[1]+i][j]+dp[st[1]+i+1][j])%MODE;
dp[st[0]+i][j]=(dp[st[0]+i][j]+dp[st[0]+i+1][j])%MODE;
}else{
dp[st[3]+i][j]=(dp[st[3]+i][j]+dp[st[1]+i+1][j])%MODE;
dp[st[2]+i][j]=(dp[st[2]+i][j]+dp[st[0]+i+1][j])%MODE;
}
}
}
return dp[0][N-1];
}

private static final Scanner scanner = new Scanner(System.in);

public static void main(String[] args) throws Exception {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
long t = System.currentTimeMillis();
int q = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])*");

for (int qItr = 0; qItr < q; qItr++) {
int aCount = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])*");

int[] a = new int[aCount];
StringBuilder sb = new StringBuilder();

for (int aItr = 0; aItr < aCount; aItr++) {
String aItem = scanner.nextLine();
//scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])*");
a[aItr] = aItem.length();
sb.append(aItem);
}
int result = palindromicStrings(a, sb.toString().toCharArray());

bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
}

bufferedWriter.close();

scanner.close();
System.out.println(System.currentTimeMillis()-t);
}
}

In C :

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

#define md 1000000007

char cv[1001], fv[1000], lv[1000], gv[1000];
unsigned int mv[1000 * 1000 * 4];
int m;

int i, j, k, l, n;
char *s;
for (i = 0; i < 1000; ++i)
{
fv[i] = 0;
lv[i] = 0;
}
s = cv;
k = 0;
scanf("%d", &n);
for (i = 0; i < n; ++i)
{
scanf("%s", s);
l = strlen(s);
fv[k] = 1;
lv[k + l - 1] = 1;
for (j = 0; j < l; ++j)
{
gv[k + j] = i;
}
k += l;
s += l;
}
m = strlen(cv);
}

int ix(int i, int j, int oi, int oj) {
return (i * m * 4) + (j * 4) + (oi * 2) + oj;
}

unsigned int f(int i, int j, int oi, int oj) {
if (i == j)
{
return (oi || oj) ? 2 : 1;
}
if (j < i)
{
return 1;
}
if (gv[i] == gv[j])
{
oi = oi || oj;
oj = oi;
}
return mv[ix(i, j, oi, oj)];
}

void run() {
int l, i, j, p;
int il, jf, oi, oj, oi1, oj1, b1, b2;
unsigned int c;
for (l = 2; l <= m; ++l)
{
for (i = 0; i <= m - l; ++i)
{
j = i + l - 1;
for (p = 0; p < 4; ++p)
{
if (p == 0 || p == 3 || gv[i] < gv[j])
{
il = lv[i];
jf = fv[j];
oi = p & 1;
oj = p >> 1;
c = 0;
b1 = oi || !il;
b2 = oj || !jf;
oi1 = !il && oi;
oj1 = !jf && oj;
if (b1)
{
c += f(i + 1, j, oi1, oj);
}
if (b2)
{
c += f(i, j - 1, oi, oj1);
}
if (b1 && b2 && (l > 2 || oi || oj))
{
c += md - f(i + 1, j - 1, oi1, oj1);
}
if (cv[i] == cv[j])
{
c += f(i + 1, j - 1, !il, !jf);
}
//printf("%d %d %d %d %u\n", i, j, oi, oj, c % md);
mv[ix(i, j, oi, oj)] = c % md;
}
}
}
}
printf("%u\n", mv[ix(0, m - 1, 0, 0)]);
}

int main() {
int q, i;
scanf("%d", &q);
for(i = 0; i < q; ++i) {
run();
}
return 0;
}```
```

## Array-DS

An array is a type of data structure that stores elements of the same type in a contiguous block of memory. In an array, A, of size N, each memory location has some unique index, i (where 0<=i<N), that can be referenced as A[i] or Ai. Reverse an array of integers. Note: If you've already solved our C++ domain's Arrays Introduction challenge, you may want to skip this. Example: A=[1,2,3

## 2D Array-DS

Given a 6*6 2D Array, arr: 1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 An hourglass in A is a subset of values with indices falling in this pattern in arr's graphical representation: a b c d e f g There are 16 hourglasses in arr. An hourglass sum is the sum of an hourglass' values. Calculate the hourglass sum for every hourglass in arr, then print t

## Dynamic Array

Create a list, seqList, of n empty sequences, where each sequence is indexed from 0 to n-1. The elements within each of the n sequences also use 0-indexing. Create an integer, lastAnswer, and initialize it to 0. There are 2 types of queries that can be performed on the list of sequences: 1. Query: 1 x y a. Find the sequence, seq, at index ((x xor lastAnswer)%n) in seqList.

## Left Rotation

A left rotation operation on an array of size n shifts each of the array's elements 1 unit to the left. Given an integer, d, rotate the array that many steps left and return the result. Example: d=2 arr=[1,2,3,4,5] After 2 rotations, arr'=[3,4,5,1,2]. Function Description: Complete the rotateLeft function in the editor below. rotateLeft has the following parameters: 1. int d

## Sparse Arrays

There is a collection of input strings and a collection of query strings. For each query string, determine how many times it occurs in the list of input strings. Return an array of the results. Example: strings=['ab', 'ab', 'abc'] queries=['ab', 'abc', 'bc'] There are instances of 'ab', 1 of 'abc' and 0 of 'bc'. For each query, add an element to the return array, results=[2,1,0]. Fun

## Array Manipulation

Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in the array. Example: n=10 queries=[[1,5,3], [4,8,7], [6,9,1]] Queries are interpreted as follows: a b k 1 5 3 4 8 7 6 9 1 Add the valu