题目:
字符串 APPAPT
中包含了两个单词 PAT
,其中第一个 PAT
是第 2 位(P
),第 4 位(A
),第 6 位(T
);第二个 PAT
是第 3 位(P
),第 4 位(A
),第 6 位(T
)。
现给定字符串,问一共可以形成多少个 PAT
?
输入格式:
输入只有一行,包含一个字符串,长度不超过105,只包含 P
、A
、T
三种字母。
输出格式:
在一行中输出给定字符串中包含多少个 PAT
。由于结果可能比较大,只输出对 1000000007 取余数的结果。
输入样例:
APPAPT
输出样例:
2
解析:
最基础的动态规划,用三个dp数组p[i],pa[i],pat[i]分别存储从0到n的字符中p,pa,pat的个数。
每当新来一个字符(这里记为i+1)时,
当它为P时,p[i+1] = p[i]+1,pa[i+1]和pat[i+1]都保持不变,因为新来的P不能和前面从0到i的任何字符组成新的"pa"或者“pat”;
当它为A时,p[i+1]和pat[i+1]分别等于p[i]和pat[i],理由如上。此时刚加进来的A可以与前面0到i个字符中的P组成新的“PA”,所以pa[i+1] = pa[i] + p[i];
当它为T时,p[i+1] = p[i],pa[i+1] = pa[i]。此时刚加进来的T可以与前面0到i个字符中的“PA”组成新的“PAT”,所以pat[i+1] = pat[i] + pa[i]。
除此之外,还需注意中间步骤对1000000007 取余。
代码:
#include<iostream>
using namespace std;
#define int long long
const int N = 1e5+5;
const int P = 1e9+7;
int p[N],pa[N],pat[N];
signed main()
{
string a;
cin>>a;
int i = 0;
while(a[i]!='\0')
{
if(a[i]=='P')
{
p[i+1] = (p[i] + 1)%P;
pa[i+1] = pa[i];
pat[i+1] = pat[i];
}
if(a[i]=='A')
{
p[i+1] = p[i];
pa[i+1] = (pa[i] + p[i])%P;
pat[i+1] = pat[i];
}
if(a[i]=='T')
{
p[i+1] = p[i];
pa[i+1] = pa[i];
pat[i+1] = (pat[i] + pa[i])%P;
}
i++;
}
cout<<pat[i];
}