一道Google top coder的850分例题及解答

本文详细解析了一道Google top coder平台上的850分例题,该题涉及到字符串排列和AB序列的概念。通过分析AB序列与字符串的对应关系,作者给出了多种解决方案,包括O(N^2)和O(N^3)复杂度的算法,并探讨了算法优化的可能性,最后提出了O(N log N)复杂度的猜想。
摘要由CSDN通过智能技术生成
一道Google top coder的850分例题及解答
 
原题:
 
假设有这样一种字符串,它们的长度不大于 26 ,而且若一个这样的字符串其长度为 m ,则这个字符串必定由 a, b, c ... z 中的前 m 个字母构成,同时我们保证每个字母出现且仅出现一次。比方说某个字符串长度为 5 ,那么它一定是由 a, b, c, d, e 这 5 个字母构成,不会多一个也不会少一个。嗯嗯,这样一来,一旦长度确定,这个字符串中有哪些字母也就确定了,唯一的区别就是这些字母的前后顺序而已。
 
现在我们用一个由大写字母 A 和 B 构成的序列来描述这类字符串里各个字母的前后顺序:
 
l          如果字母 b 在字母 a 的后面,那么序列的第一个字母就是 A (After),否则序列的第一个字母就是 B (Before);
l          如果字母 c 在字母 b 的后面,那么序列的第二个字母就是 A ,否则就是 B;
l          如果字母 d 在字母 c 的后面,那么 …… 不用多说了吧?直到这个字符串的结束。
 
这规则甚是简单,不过有个问题就是同一个 AB 序列,可能有多个字符串都与之相符,比方说序列"ABA",就有"acdb"、"cadb"等等好几种可能性。说的专业一点,这一个序列实际上对应了一个字符串集合。那么现在问题来了:给你一个这样的AB 序列,问你究竟有多少个不同的字符串能够与之相符?或者说这个序列对应的字符串集合有多大?注意,只要求个数,不要求枚举所有的字符串。
 
注:如果结果大于10亿就返回-1。
 
 
我的最终解答(没有考虑溢出的情况):
 
// CODE 1
// the best way
// O(N^2)
int countABbest(const string& AB)
{
    assert(AB.find_first_not_of("AB") == string::npos);
 
    vector<int> current, next; // should we reserve these vectors?
    current.push_back(1);
 
    for (string::const_iterator letter = AB.begin();
        letter != AB.end(); ++letter) {
        next.resize(current.size()+1); // or next.insert(next.end(), 2, 0);
        next[0] = 0; // in fact, we could set the entire vector to zero
 
        if (*letter == 'A') {
            partial_sum(current.begin(), current.end(), next.begin()+1);
        } else {
            partial_sum(current.rbegin(), current.rend(), next.begin()+1);
            reverse(next.begin(), next.end());
        }
        swap(current, next);
    }
    return accumulate(current.begin(), current.end(), 0);
}
 
int main()
{
    const char* AB = "ABBAAB";
    printf("'%s' : %d/n", AB, countABbest(AB));
}
 
下面谈一谈我在解决这个问题时的思路。
 
第一步 初步分析
 
以下“字符串”特指题目中提到的由小写字母a、b、c等等组成的字符串,每个字母出现且仅出现一次。显然题目要求我们写一个函数f,f的输入是一个长度为v 的AB序列w,w代表了一个字符串集合s(集合中的元素都是长度为m(m=v+1)的字符串),f的返回值是这个集合的元素个数|s|,即|s|=f(w)。用高中学过的一点排列组合知识,可分析知:
1.        长度为m的字符串有m! 个(’!’ 表示阶乘)因为这相当于m个不同字母的全排列;
2.        长度为v的AB序列有2^v个(’^’ 表示指数)因为每个位置有2种可能,一共有v个位置;
3.        由于2^v <= m! (m=v+1),所以AB序列的数目不大于字符串的数目。
4.
  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值