Maximum Palindromes


Problem Statement :


Madam Hannah Otto, the CEO of Reviver Corp., is fond of palindromes, or words that read the same forwards or backwards. She thinks palindromic brand names are appealing to millennials.

As part of the marketing campaign for the company's new juicer called the Rotator™, Hannah decided to push the marketing team's palindrome-searching skills to a new level with a new challenge.

In this challenge, Hannah provides a string  consisting of lowercase English letters. Every day, for  days, she would select two integers  and , take the substring  (the substring of  from index  to index ), and ask the following question:

Consider all the palindromes that can be constructed from some of the letters from . You can reorder the letters as you need. Some of these palindromes have the maximum length among all these palindromes. How many maximum-length palindromes are there?

Input Format

The first line contains the string .

The second line contains a single integer .

The  of the next  lines contains two space-separated integers ,  denoting the  and  values Anna selected on the 


Output Format

For each query, print a single line containing a single integer denoting the answer.



Solution :



title-img


                            Solution in C :

In  C++  :






#include <cstdio>
#include <cmath>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cassert>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i = a; i < b; i++)
#define S(x) scanf("%d",&x)
#define S2(x,y) scanf("%d%d",&x,&y)
#define P(x) printf("%d\n",x)
#define all(v) v.begin(),v.end()
#define FF first
#define SS second
#define pb push_back
#define mp make_pair

typedef long long int LL;
typedef pair<int, int > pii;
typedef vector<int > vi;

const int mod = 1000000007;
const int N = 100005;

LL F[N], IF[N];

LL _pow(LL a, LL b) {
  if(!b) return 1;
  if(b == 1) return a;
  if(b == 2) return a * a % mod;
  if(b & 1) {
    return a * _pow(a,b-1) % mod;
  }
  return _pow(_pow(a,b/2),2);
}

void pre() {
  F[0] = 1;
  rep(i,1,N) {
    F[i] = i * F[i-1] % mod;
  }
  IF[N - 1] = _pow(F[N - 1], mod - 2);
  for(int i = N - 2; i >= 0; i--) {
    IF[i] = IF[i + 1] * (i + 1) % mod;
  }
}

int X[26][N];

int main() {
  pre();
  string s;
  cin >> s;
  int n = s.size();
  rep(i,0,n) {
    rep(j,0,26) X[j][i+1] = X[j][i];
    X[s[i]-'a'][i+1]++;
  }
  int q;
  S(q);
  while(q--) {
    int l,r;
    S2(l,r);
    int tot = 0;
    LL ans = 1;
    int odd = 0;
    rep(i,0,26) {
      int x = X[i][r] - X[i][l-1];
      odd += (x&1);
      ans *= IF[x / 2];
      ans %= mod;
      tot += x / 2;
    }
    ans *= F[tot];
    ans %= mod;
    if(odd) ans = ans * odd % mod;
    printf("%lld\n",ans);
  }
  return 0;
}









In   Java  :








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

public class Solution {

    static int[][] count;
    static long[] f;
    static long mod = 1000000007;
    
    static void initialize(String s)
    {
        count = new int[s.length()][26];
        
        for (int i = 0; i < s.length(); i++)
        {
            if (i > 0)
            {
                for (int j = 0; j < 26; j++) count[i][j] = count[i-1][j];
            }
            
            count[i][s.charAt(i) - 'a']++;
        }
        
        f = new long[100000];
        f[0] = 1;
        
        for (int i = 1; i < 100000; i++) f[i] = f[i - 1] * i % mod;
    }

    static int c[] = new int[26];
        
    static int answerQuery(int l, int r) {
        // Return the answer for this query modulo 1000000007.
        
        l--;
        r--;
        
        for (int i = 0; i < 26; i++)
        {
            c[i] = count[r][i];
            
            if (l > 0)
            {
                c[i] -= count[l - 1][i];
            }
        }
        
        int len = 0;
        int oddCount = 0;
        
        for (int i = 0; i < 26; i++)
        {
            len += c[i] / 2;
            if (c[i] % 2 == 1) oddCount++;
        }
        
        long ans = f[len];
        long div = 1;
        
        for (int i = 0; i < 26; i++)
        {
            if (c[i] >= 4)
            {
                div *= f[c[i] / 2];
                div %= mod;
            }
        }
        
        if (div != 1) ans = solveCongruence(div, ans, mod);
        
        if (oddCount > 0)
        {
            ans *= oddCount;
            ans %= mod;
        }
        
        return (int) ans;
    }
    
    static long solveCongruence(long a, long b, long mod)
	{
		if (a == 1)
		{
			return b;
		}

		long b1 = -b%a;

		if (b1 != 0)
		{
			b1 += a;
		}

		long y = solveCongruence(mod % a, b1, a);
		return (mod * y + b) / a % mod;
	}


    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String s = in.next();
        initialize(s);
        int q = in.nextInt();
        for(int a0 = 0; a0 < q; a0++){
            int l = in.nextInt();
            int r = in.nextInt();
            int result = answerQuery(l, r);
            System.out.println(result);
        }
        in.close();
    }
}









In   C  :








#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

#define MOD 1000000007
#define MAX 100000
#define MAXP 100000

int a[MAX+1][26];
long fact[MAX+1];

void initialize(char* s) {
  for(int j=0; j<26; j++) {
    a[0][j] = 0;
  }
  for(int i=0; s[i]; i++) {
    for(int j=0; j<26; j++) {
      a[i+1][j] = a[i][j];
    }
    a[i+1][s[i]-'a'] ++;
    /*for(int j=0; j<26; j++) {
      printf("a[until(inc) %c][for %c] = %d\n", s[i], j+'a', a[i+1][j]);
    }*/
  }
  fact[0] = 1L;
  for(int i=0; s[i]; i++) {
    fact[i+1] = (fact[i]*(i+1))%MOD;
  }
}

long dinv(long x) {
  int i;
  static long r[MAXP], s[MAXP], t[MAXP], q[MAXP];
  r[0] = MOD; r[1] = x;
  s[0] = 1; s[1] = 0;
  t[0] = 0; t[1] = 1;
  i = 1;
  while(r[i] > 0) {
    q[i] = r[i-1]/r[i];
    r[i+1] = r[i-1] - q[i]*r[i];
    s[i+1] = s[i-1] - q[i]*s[i];
    t[i+1] = t[i-1] - q[i]*t[i];
    //printf("%ld %ld %ld\n", r[i+1], s[i+1], t[i+1]);
    i ++;
  }
  return (t[i-1]+MOD)%MOD;
}

int answerQuery(char* s, int l, int r) {
  int v[26];
  long res;
  for(int i=0; i<26; i++) {
    v[i] = a[r][i] - a[l-1][i];
  }
  /*for(int i=0; i<26; i++) {
    printf("v[%c] = %d\n", i+'a', v[i]);
  }
  printf("\n");*/
  int oddcount = 0;
  int eventotal = 0;
  for(int i=0; i<26; i++) {
    oddcount += v[i]%2;
    eventotal += v[i]/2;
  }
  res = fact[eventotal];
  if(oddcount > 0) {
    res = (res*oddcount)%MOD;
  }
  for(int i=0; i<26; i++) {
    if(v[i]/2 > 0) {
      res = (res*dinv(fact[v[i]/2]))%MOD;
    }
  }
  return (int)res;
}

int main() {
    char* s = (char *)malloc(512000 * sizeof(char));
    scanf("%s", s);
    initialize(s);
    int q; 
    scanf("%i", &q);
    for(int a0 = 0; a0 < q; a0++){
        int l; 
        int r; 
        scanf("%i %i", &l, &r);
        int result = answerQuery(s, l, r);
        printf("%d\n", result);
    }
    return 0;
}









In   Python3 :







from collections import defaultdict
from copy import copy

M = int(1e9) + 7
fact = [1]
for i in range(1,int(1e5) + 10):
    fact.append(fact[-1]*i % M)

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

memo = {}
def modinv(a, m):
    if a in memo:
        return memo[a]
    while a < 0:
        a += m
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('Modular inverse does not exist')
    else:
        memo[a] = x%m
        return x % m


s = input().strip()
occ = [defaultdict(int)]
for ch in s:
    newd = copy(occ[-1])
    newd[ch] += 1
    occ.append(newd)
    
def query(l, r):
    d = defaultdict(int)
    for ch in occ[r]:
        d[ch] += occ[r][ch]
    for ch in occ[l-1]:
        d[ch] -= occ[l-1][ch]
        
    odds = 0
    for k, v in copy(d).items():
        if v&1:
            odds += 1
        d[k] = v - (v&1)
        
    res = 1
    total = 0
    for k, v in d.items():
        res *= modinv(fact[v//2], M)
        total += v//2
        res %= M
    return (max(1, odds)*res*fact[total])%M

for _ in range(int(input())):
    l, r = map(int, input().split())
    print(query(l, r))
                        








View More Similar Problems

Tree: Inorder Traversal

In this challenge, you are required to implement inorder traversal of a tree. Complete the inorder function in your editor below, which has 1 parameter: a pointer to the root of a binary tree. It must print the values in the tree's inorder traversal as a single line of space-separated values. Input Format Our hidden tester code passes the root node of a binary tree to your $inOrder* func

View Solution →

Tree: Height of a Binary Tree

The height of a binary tree is the number of edges between the tree's root and its furthest leaf. For example, the following binary tree is of height : image Function Description Complete the getHeight or height function in the editor. It must return the height of a binary tree as an integer. getHeight or height has the following parameter(s): root: a reference to the root of a binary

View Solution →

Tree : Top View

Given a pointer to the root of a binary tree, print the top view of the binary tree. The tree as seen from the top the nodes, is called the top view of the tree. For example : 1 \ 2 \ 5 / \ 3 6 \ 4 Top View : 1 -> 2 -> 5 -> 6 Complete the function topView and print the resulting values on a single line separated by space.

View Solution →

Tree: Level Order Traversal

Given a pointer to the root of a binary tree, you need to print the level order traversal of this tree. In level-order traversal, nodes are visited level by level from left to right. Complete the function levelOrder and print the values in a single line separated by a space. For example: 1 \ 2 \ 5 / \ 3 6 \ 4 F

View Solution →

Binary Search Tree : Insertion

You are given a pointer to the root of a binary search tree and values to be inserted into the tree. Insert the values into their appropriate position in the binary search tree and return the root of the updated binary tree. You just have to complete the function. Input Format You are given a function, Node * insert (Node * root ,int data) { } Constraints No. of nodes in the tree <

View Solution →

Tree: Huffman Decoding

Huffman coding assigns variable length codewords to fixed length input characters based on their frequencies. More frequent characters are assigned shorter codewords and less frequent characters are assigned longer codewords. All edges along the path to a character contain a code digit. If they are on the left side of the tree, they will be a 0 (zero). If on the right, they'll be a 1 (one). Only t

View Solution →