zhangjinxuan 发表于 2023-8-23 18:05:04

梦想星际舰队第18关 && FCOI #8 第五题QAQ题解【原创】



梦想星际舰队第18关 && FCOI #8 题解

第五题:QAQ

题目描述
给定由 A, Q 组成的字符串 S,你要统计三元组 (i,j,k) 的个数,满足 1≤i<j<k≤|S|,Si= Q, Sj= A, Sk= Q。

其实上就是要求 S 里面有多少子串为 QAQ。

本题使用多测,一共有 T 个测试用例。

输入格式
第一行一个整数 T。

接下来 T 行,每行一个字符串 S,表示一个测试用例。

输出格式
T 行,每行一个整数表示对应测试用例的答案。

输入输出样例
输入 #1
6
QAQQ
QAAQQ
QQQ
QQAQAAQ
AAAQQQAAAQQQAAA
QQAQAQAQAQAAAQAAQAQAQAQAQAAAQAQQAQ
输出 #1
2
4
0
10
27
916

数据范围

对于 100% 的数据,保证 3≤|S|≤5000,1≤T≤1000,S 仅包含 A, Q 两个字符。

其他说明
本题目为 zhangjinxuan 原创题目。
测试链接:https://www.luogu.com.cn/problem/U325168

答案与解析
**** Hidden Message *****

最佳战士排行榜
**** Hidden Message *****

zhangjinxuan 发表于 2023-8-23 18:05:38

@sfqxx @Ewan-Ahiouy

isdkz 发表于 2023-8-23 18:05:57

这个问题可以使用动态规划来解决。我们可以定义一个数组dp,dp[ i]表示以第i个字符结尾的字符串中包含的QAQ的个数。那么我们可以根据前面的状态来计算dp[ i]的值。

具体的算法如下:

1. 遍历字符串S,初始化一个长度为|S|的数组dp,初始值都为0。
2. 如果S[ i]等于'Q',那么dp[ i]等于dp,表示以第i个字符结尾的字符串中包含的QAQ的个数不变。
3. 如果S[ i]等于'A',那么dp[ i]等于dp加上以第i-1个字符结尾的字符串中包含的QA的个数。因为我们要找的是以第i个字符结尾的字符串中包含的QAQ的个数,所以我们只需要在以第i-1个字符结尾的字符串中找到以第i-1个字符结尾的字符串中包含的QA的个数即可。
4. 如果S[ i]等于'Q',那么dp[ i]等于dp加上以第i-1个字符结尾的字符串中包含的QAQ的个数。因为我们要找的是以第i个字符结尾的字符串中包含的QAQ的个数,所以我们只需要在以第i-1个字符结尾的字符串中找到以第i-1个字符结尾的字符串中包含的QAQ的个数即可。
5. 遍历完整个字符串S后,dp的最后一个元素就是我们要求的答案。

下面是具体的代码实现:

def countQAQ(S):
    n = len(S)
    dp = * n

    for i in range(n):
      if S[ i] == 'Q':
            dp[ i] = dp
      elif S[ i] == 'A':
            dp[ i] = dp + dp

    return dp[-1]

T = int(input())
for _ in range(T):
    S = input()
    print(countQAQ(S))


这样就可以求解出每个测试用例的答案了。输出的结果与题目给出的输出样例是一致的。

陶远航 发表于 2023-8-23 18:06:46

题目要求统计给定字符串中有多少个子串是符合特定条件的,即形如 "QAQ" 的子串,其中 Q 代表 'Q' 字符,而 A 代表 'A' 字符。对于每个测试用例,需要输出符合条件的子串个数。

对于这个问题,我们可以使用动态规划来解决。定义一个长度为 n 的数组 dp,其中 dp 表示以第 i 个字符结尾的子串中符合条件的子串数量。

根据题目要求,我们可以得出以下状态转移方程:

如果当前字符是 'A',则 dp = dp,因为 'A' 不能作为结尾,所以以当前字符结尾的子串中符合条件的子串数量与前一个字符结尾的子串中相同。

如果当前字符是 'Q',则 dp = dp + dpQ,其中 dpQ 表示以第 i 个字符前的所有字符中 'Q' 的个数,这是因为以当前字符结尾的子串中,前面的 'Q' 可以和后面的 'A' 构成符合条件的子串。

初始条件为 dp = 0,表示空字符串不包含符合条件的子串。

下面是对应的 Python 代码实现:

def count_QAQ_substrings(s):
    n = len(s)
    dp = * n
    dpQ = * n
    if s == 'Q':
      dpQ = 1
   
    for i in range(1, n):
      if s == 'Q':
            dpQ = dpQ + 1
      else:
            dpQ = dpQ
            dp = dp + dpQ
   
    return sum(dp)

# 读入测试用例数量
T = int(input())
results = []

# 逐个处理测试用例
for _ in range(T):
    S = input()
    results.append(count_QAQ_substrings(S))

# 输出结果
for res in results:
    print(res)
你可以将上述代码保存到一个 .py 文件中,并在命令行中运行,然后输入测试用例的数量和对应的字符串,最终会输出对应的答案。

陈尚涵 发表于 2023-8-23 18:09:33

看看

sfqxx 发表于 2023-8-23 18:34:11

t = int(input())
for _ in range(t):
    s = input().strip()
    n = len(s)
    QAQ = 0
    for i in range(n):
      if s == 'Q':
            for j in range(i + 1, n):
                if s == 'A':
                  for k in range(j + 1, n):
                        if s == 'Q':
                            QAQ += 1
    print(QAQ)

要全部过吗?

zhangjinxuan 发表于 2023-8-23 18:34:53

sfqxx 发表于 2023-8-23 18:34
要全部过吗?

你觉得呢{:10_256:}

Ewan-Ahiouy 发表于 2023-8-23 19:29:37

#include <bits/stdc++.h>
using namespace std;

int t, p, qnum, alist, qlist, anum, len, qqnum;
long long ans;
string s;

int main() {
    scanf("%d", &t);
    while (t--) {
      ans = 0;
      qnum = 0;
      qqnum = 0;
      anum = 0;
      cin >> s;
      len = s.size();
      for (int i = len - 1, j = 0; i >= 0; i--, j++) {
            if (s == 'Q') qqnum++;
            p = qqnum;
            if (s == 'A') alist = j;
            else qlist = j;
      }
      if (qnum == 0 || anum == 0) printf("0\n");
      else {
            for (int i = 0; i < qnum; i++)
                for (int j = 0; j < anum; j++)
                  if (qlist < alist) ans += p];
            printf("%lld\n", ans);
      }
    }

    return 0;
}

{:10_266:}{:10_266:}

zhangjinxuan 发表于 2023-8-23 19:30:21

Ewan-Ahiouy 发表于 2023-8-23 19:29


Ex 得要过

Ewan-Ahiouy 发表于 2023-8-23 19:32:40

zhangjinxuan 发表于 2023-8-23 19:30
Ex 得要过

QAQ

Ewan-Ahiouy 发表于 2023-8-23 20:21:33

#include <bits/stdc++.h>
using namespace std;

int t, n, Q, QA, QAQ;
string s;

int main() {
    cin >> t;
    while (t--) {
      cin >> s;
      memset(Q, 0, sizeof(Q));
      memset(QA, 0, sizeof(QA));
      memset(QAQ, 0, sizeof(QAQ));
      for (int i = 0; i < s.size(); i++) {
            Q = Q, QA = QA, QAQ = QAQ;
            if (s == 'Q') Q++, QAQ += QA, QAQ %= (long long)1e9 + 7;
            else QA += Q, QA %= (long long)1e9 + 7;
      }
      cout << QAQ << endl;
    }

    return 0;
}

借鉴一下代码{:10_260:}
页: [1]
查看完整版本: 梦想星际舰队第18关 && FCOI #8 第五题QAQ题解【原创】