PAT(Advanced) 甲级1093 Count PAT’s C++实现
题目链接
题目大意
输入仅含’P’,‘A’,'T’三种字符的字符串序列,输出字符串序列可以组成子串"PAT"的最大个数。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
int main(int argc, char const *argv[])
{
string str;
while (cin >> str) {
int P = 0, A = 0, T = 0;//初始三种字符个数为0
// P为能够得到的最多"PAT"子串数目, A为能够得到的最多"AT"子串的数目(对于每个有效的'P'字符,A为当前其后所有的"AT"子串数目), T为字符串中所有有效"T"字符的个数(对于每个有效'A'位置,T为当前其后的所有有效‘T’字符个数)
int lastT = str.size() - 1;//从字符串最后一个字符开始
while (str[lastT] != 'T' && lastT >= 0) lastT--;//找到字符串末尾的首个字符'T'
//根据题意可知,最后一个'T'字符后面的'P'和'A'字符对最终结果没有意义
while (str[lastT] != 'A' && lastT >= 0) {
if (str[lastT] == 'T') {
T++;
}
lastT--;
}
//搜索最后一个'A' 和最后一个'T'字符之间存在的所有'T',在最后一个'A'之后的所有'P'字符没有意义
//搜索到最后一个字符'A'的所有字符‘T’都需要累加到变量T中,在'A'后的所有'T'有意义
//同理,在'P'之后的所有'A'和'T'有意义
int lastA = lastT;
while (str[lastA] != 'A' && lastA >= 0) lastA--;
for (int i = lastA; i >= 0; i--) {
if (str[i] == 'T') {//遇到'T',变量T自增
T++;
T %= MOD;
} else if (str[i] == 'A') {//遇到'A',此处后面所有的'T'为可以组成的"AT"数量,累加入变量A
A += T;
A %= MOD;
} else if (str[i] == 'P') {//遇到'P',此处所有的"AT”子串与其可以组成"PAT"子串,累加入变量P
P += A;
P %= MOD;
}
}
printf("%d\n", P);
str.clear();
}
return 0;
}
算法思路
设置三个变量P,A,T,P为能够得到的最多"PAT"子串数目, A为能够得到的最多"AT"子串的数目(对于每个有效的’P’字符,A为当前其后所有的"AT"子串数目), T为字符串中所有有效"T"字符的个数(对于每个有效’A’位置,T为当前其后的所有有效‘T’字符个数)。在最后一个for循环过程中,不断更新T的个数和子串"AT"的个数,一个’A’字符和其后所有的T个’T’字符可以构成T个"AT"子串,一个’P’字符可以和其后所有的A个"AT"子串构成"PAT"子串,不断累加即可得到答案。
本题算法只扫描整个字符串一次,问题规模n下,时间复杂度O(n)。
详情已在上述AC代码部分注释说明!
样例输入
APPAPT
样例输出
2
鸣谢
感谢PAT提供的题目及测评平台
最后
需要注意的是,在前面几个循环对最后一个’A’字符和最后一个’T’字符的处理,最后一个’A’字符和最后一个’T’字符之间的所有’T’字符有效,博主之前忽略了这一部分的处理而导致输出不能全部正确。
由于博主水平有限,不免有疏漏之处,欢迎读者随时批评指正,以免造成不必要的误解!