题目描述
两伙外星人策划在未来的XXXX年侵略地球,侵略前自然要交换信息咯,现在,作为全球保卫队队长,你截获了外星人用来交换信息的一段仅由“F”,“B”,“I”,“O”组成的序列。为了保卫地球和平,为了使家园不受破坏,你要机智地破解密码,勇敢地迎击外星人!记住,你不是一个人在战斗!你不是一个人!你的背后是千千万万的地球人!
输入输出格式
输入格式
一组仅由“F”、“B”、“I”、“0”组成的序列(“F”、“B”、“I”、“0”这四个字母中的某一个或某几个不一定会出现,且保证序列长度≤2000)
规定这个序列所要传达的信息就是这组序列有多少个“FBI”(子序列)
输出格式
一行,一个数,表示这组序列有多少个“FBI”的子序列(保证答案≤2^31,且FBI必须是正序,即IBF或者BIF或者FIB或者BFI或者IFB都不能算是一个FBI)
输入输出样例
输入样例
FBIIBFOI
输出样例
4
题解
朴素做法很明显,枚举F,B,I的位置,暴力统计,时间复杂度O(n³),数据水的话还能卡过去。
显然我们不能用这种做法。可以考虑枚举B的位置i(假设从1开始计数),然后统计字符串的第一位到第i-1位里F的数量和第i+1位到第n位I的数量,根据乘法原理统计结果,而事实上统计F,I的数量也可以用两个变量维护,枚举i的过程中判断要不要更改这两个变量,这样即可做到O(n)的时间复杂度。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; char s[2005]; int len; int cnt_F, cnt_I; int ans; int main() { scanf("%s", s); len = strlen(s); for(register int i = 0; i < len; ++i) { if(s[i] == 'I') ++cnt_I; } for(register int i = 0; i < len; ++i) { if(s[i] == 'B') ans += cnt_F * cnt_I; else if(s[i] == 'F') ++cnt_F; else if(s[i] == 'I') --cnt_I; } printf("%d", ans); }