GHOJ 232 FBI序列

题目描述

        两伙外星人策划在未来的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);
}
参考程序
原文地址:https://www.cnblogs.com/kcn999/p/10353481.html