鱼C论坛

 找回密码
 立即注册
查看: 1499|回复: 10

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

[复制链接]
发表于 2023-8-23 18:05:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x


梦想星际舰队第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
  1. 6
  2. QAQQ
  3. QAAQQ
  4. QQQ
  5. QQAQAAQ
  6. AAAQQQAAAQQQAAA
  7. QQAQAQAQAQAAAQAAQAQAQAQAQAAAQAQQAQ
复制代码

输出 #1
  1. 2
  2. 4
  3. 0
  4. 10
  5. 27
  6. 916
复制代码


数据范围

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

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

答案与解析
游客,如果您要查看本帖隐藏内容请回复
[/hide]

最佳战士排行榜
游客,如果您要查看本帖隐藏内容请回复
[/hide]
最佳答案
2023-8-23 20:21:33
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. int t, n, Q[5001], QA[5001], QAQ[5001];
  4. string s;

  5. int main() {
  6.     cin >> t;
  7.     while (t--) {
  8.         cin >> s;
  9.         memset(Q, 0, sizeof(Q));
  10.         memset(QA, 0, sizeof(QA));
  11.         memset(QAQ, 0, sizeof(QAQ));
  12.         for (int i = 0; i < s.size(); i++) {
  13.             Q[i] = Q[i - 1], QA[i] = QA[i - 1], QAQ[i] = QAQ[i - 1];
  14.             if (s[i] == 'Q') Q[i]++, QAQ[i] += QA[i - 1], QAQ[i] %= (long long)1e9 + 7;
  15.             else QA[i] += Q[i - 1], QA[i] %= (long long)1e9 + 7;
  16.         }
  17.         cout << QAQ[s.size() - 1] << endl;
  18.     }

  19.     return 0;
  20. }
复制代码


借鉴一下代码

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-8-23 18:05:38 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

下面是具体的代码实现:

  1. def countQAQ(S):
  2.     n = len(S)
  3.     dp = [0] * n

  4.     for i in range(n):
  5.         if S[ i] == 'Q':
  6.             dp[ i] = dp[i-1]
  7.         elif S[ i] == 'A':
  8.             dp[ i] = dp[i-1] + dp[i-1]

  9.     return dp[-1]

  10. T = int(input())
  11. for _ in range(T):
  12.     S = input()
  13.     print(countQAQ(S))
复制代码


这样就可以求解出每个测试用例的答案了。输出的结果与题目给出的输出样例是一致的。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

发表于 2023-8-23 18:06:46 | 显示全部楼层
题目要求统计给定字符串中有多少个子串是符合特定条件的,即形如 "QAQ" 的子串,其中 Q 代表 'Q' 字符,而 A 代表 'A' 字符。对于每个测试用例,需要输出符合条件的子串个数。

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

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

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

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

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

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

  1. def count_QAQ_substrings(s):
  2.     n = len(s)
  3.     dp = [0] * n
  4.     dpQ = [0] * n
  5.     if s[0] == 'Q':
  6.         dpQ[0] = 1
  7.    
  8.     for i in range(1, n):
  9.         if s[i] == 'Q':
  10.             dpQ[i] = dpQ[i-1] + 1
  11.         else:
  12.             dpQ[i] = dpQ[i-1]
  13.             dp[i] = dp[i-1] + dpQ[i-1]
  14.    
  15.     return sum(dp)

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

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

  23. # 输出结果
  24. for res in results:
  25.     print(res)
复制代码

你可以将上述代码保存到一个 .py 文件中,并在命令行中运行,然后输入测试用例的数量和对应的字符串,最终会输出对应的答案。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

发表于 2023-8-23 18:09:33 | 显示全部楼层
看看
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-8-23 18:34:11 | 显示全部楼层
  1. t = int(input())
  2. for _ in range(t):
  3.     s = input().strip()
  4.     n = len(s)
  5.     QAQ = 0
  6.     for i in range(n):
  7.         if s[i] == 'Q':
  8.             for j in range(i + 1, n):
  9.                 if s[j] == 'A':
  10.                     for k in range(j + 1, n):
  11.                         if s[k] == 'Q':
  12.                             QAQ += 1
  13.     print(QAQ)
复制代码


要全部过吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-23 18:34:53 | 显示全部楼层

你觉得呢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-23 19:29:37 | 显示全部楼层
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. int t, p[5010], qnum, alist[5010], qlist[5010], anum, len, qqnum;
  4. long long ans;
  5. string s;

  6. int main() {
  7.     scanf("%d", &t);
  8.     while (t--) {
  9.         ans = 0;
  10.         qnum = 0;
  11.         qqnum = 0;
  12.         anum = 0;
  13.         cin >> s;
  14.         len = s.size();
  15.         for (int i = len - 1, j = 0; i >= 0; i--, j++) {
  16.             if (s[i] == 'Q') qqnum++;
  17.             p[i] = qqnum;
  18.             if (s[j] == 'A') alist[anum++] = j;
  19.             else qlist[qnum++] = j;
  20.         }
  21.         if (qnum == 0 || anum == 0) printf("0\n");
  22.         else {
  23.             for (int i = 0; i < qnum; i++)
  24.                 for (int j = 0; j < anum; j++)
  25.                     if (qlist[i] < alist[j]) ans += p[alist[j]];
  26.             printf("%lld\n", ans);
  27.         }
  28.     }

  29.     return 0;
  30. }
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-23 19:30:21 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-23 19:32:40 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-23 20:21:33 | 显示全部楼层    本楼为最佳答案   
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. int t, n, Q[5001], QA[5001], QAQ[5001];
  4. string s;

  5. int main() {
  6.     cin >> t;
  7.     while (t--) {
  8.         cin >> s;
  9.         memset(Q, 0, sizeof(Q));
  10.         memset(QA, 0, sizeof(QA));
  11.         memset(QAQ, 0, sizeof(QAQ));
  12.         for (int i = 0; i < s.size(); i++) {
  13.             Q[i] = Q[i - 1], QA[i] = QA[i - 1], QAQ[i] = QAQ[i - 1];
  14.             if (s[i] == 'Q') Q[i]++, QAQ[i] += QA[i - 1], QAQ[i] %= (long long)1e9 + 7;
  15.             else QA[i] += Q[i - 1], QA[i] %= (long long)1e9 + 7;
  16.         }
  17.         cout << QAQ[s.size() - 1] << endl;
  18.     }

  19.     return 0;
  20. }
复制代码


借鉴一下代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-4 06:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表