using System;
using System.Collections.Generic;
class Program
{
private const int MOD = 1000000007;
static void Main(string[] args)
{
string inputLine = Console.ReadLine();
if (string.IsNullOrEmpty(inputLine))
{
return; // Jeśli brak danych wejściowych, zakończ program
}
string[] lines = inputLine.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
if (!int.TryParse(lines[0], out int t) || t <= 0)
{
return;
}
for (int i = 1; i <= t; i++)
{
if (i >= lines.Length)
{
return; // Jeśli brakuje przypadków testowych, zakończ
}
string line = lines[i];
string[] input = line.Split();
if (input.Length != 2 || !int.TryParse(input[1], out int length))
{
return; // Jeśli format testu jest niepoprawny, zakończ
}
string regex = input[0];
Console.WriteLine(CountStrings(regex, length));
}
}
static int CountStrings(string regex, int length)
{
RegexEvaluator evaluator = new RegexEvaluator(regex);
return evaluator.CountRecognizedStrings(length);
}
class RegexEvaluator
{
private readonly string regex;
private readonly Dictionary<(string, int), int> memo;
public RegexEvaluator(string regex)
{
this.regex = regex;
this.memo = new Dictionary<(string, int), int>();
}
public int CountRecognizedStrings(int length)
{
return CountStringsHelper(regex, length);
}
private int CountStringsHelper(string expr, int length)
{
if (memo.ContainsKey((expr, length)))
return memo[(expr, length)];
if (length == 0)
{
return expr.Contains("*") || expr == "" ? 1 : 0;
}
if (expr == "a" || expr == "b")
{
return length == 1 ? 1 : 0;
}
int result = 0;
if (expr.StartsWith("("))
{
int closingIndex = FindClosingParenthesis(expr);
// Handle star (*) operator
if (closingIndex + 1 < expr.Length && expr[closingIndex + 1] == '*')
{
string inner = expr.Substring(1, closingIndex - 1);
result = ComputeStarOperator(inner, length);
}
// Handle OR (|) operator
else if (expr.Substring(1, closingIndex - 1).Contains("|"))
{
string[] parts = SplitByOperator(expr.Substring(1, closingIndex - 1), '|');
foreach (string part in parts)
{
result = (result + CountStringsHelper(part, length)) % MOD;
}
}
// Handle concatenation
else
{
string left = expr.Substring(1, closingIndex - 1);
string right = expr.Substring(closingIndex + 1);
for (int i = 0; i <= length; i++)
{
result = (result + (int)((long)CountStringsHelper(left, i) * CountStringsHelper(right, length - i) % MOD)) % MOD;
}
}
}
memo[(expr, length)] = result;
return result;
}
private int ComputeStarOperator(string expr, int length)
{
long result = 1; // Include the empty string
long baseCount = CountStringsHelper(expr, 1);
long multiplier = 1;
for (int i = 1; i <= length; i++)
{
multiplier = (multiplier * baseCount) % MOD;
result = (result + multiplier) % MOD;
if (multiplier == 0) break; // Optimization: Stop if no more valid strings
}
return (int)result;
}
private int FindClosingParenthesis(string expr)
{
int balance = 0;
for (int i = 0; i < expr.Length; i++)
{
if (expr[i] == '(') balance++;
if (expr[i] == ')') balance--;
if (balance == 0) return i;
}
throw new ArgumentException($"Invalid expression: unbalanced parentheses at position {expr.Length}");
}
private string[] SplitByOperator(string expr, char op)
{
List<string> parts = new List<string>();
int balance = 0;
int start = 0;
for (int i = 0; i < expr.Length; i++)
{
if (expr[i] == '(') balance++;
if (expr[i] == ')') balance--;
if (balance == 0 && expr[i] == op)
{
parts.Add(expr.Substring(start, i - start));
start = i + 1;
}
}
parts.Add(expr.Substring(start));
return parts.ToArray();
}
}
}