微软必应·英雄会第三届在线编程大赛:几个bing?

题目详情

    本届大赛由微软必应词典冠名,必应词典(http://cn.bing.com/dict/?form=BDVSP4&mkt=zh-CN&setlang=ZH)是微软推出的新一代英语学习引擎,里面收录了很多我们常见的单词。但现实生活中,我们也经常能看到一些毫无规则的字符串,导致词典无法正常收录,不过,我们是否可以从无规则的字符串中提取出正规的单词呢?

   例如有一个字符串"iinbinbing",截取不同位置的字符‘b’、‘i’、‘n’、‘g’组合成单词"bing"。若从1开始计数的话,则‘b’ ‘i’ ‘n’ ‘g’这4个字母出现的位置分别为(4,5,6,10) (4,5,9,10),(4,8,9,10)和(7,8,9,10),故总共可以组合成4个单词”bing“。

  咱们的问题是:现给定任意字符串,只包含小写‘b’ ‘i’ ‘n’ ‘g’这4种字母,请问一共能组合成多少个单词bing?

  字符串长度不超过10000,由于结果可能比较大,请输出对10^9 + 7取余数之后的结果。

选择方法二,结果失败了!
方法一:递归过多堆栈溢出(字符串长度不能超过几百)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bing个数
{
    /// <summary>
    /// 一、首先去掉字符串首尾的无关字符,使其成为如下格式:b......g
    /// 二、确定"b"后第一个"i"后"n"的个数计数;再找第二个"i"后"n"的个数计数...直到所有的"i"后"n"都被找完。
    /// 三、确定倒数第二个"g"字符(去掉字符串右端的无关字符),递归步骤二...直到第一个有用的"g"被找完
    /// 四、确定第二个"b"(去掉字符串左端的无关字符),重复步骤二、三...直到最后一个有用的"b"被找完
    /// </summary>
    class Program
    {
        /// <summary>
        /// b......g间所能组成bing所有方案个数
        /// </summary>
        /// <param name="oldstr"> 原先字符串 </param>
        /// <param name="newstr"> 操作字符串,通过"i"找到后面"n"的个数 </param>
        /// <param name="count"> 个数</param>
        /// <returns></returns>
        public static void getCount( string oldstr, string newstr, ref int count)
        {
            //newstr = "hjsdhifdnnsi";
            int indexI = newstr.IndexOf('i' );
            if (indexI > 0)
            {
                StringBuilder m = new StringBuilder();
                StringBuilder n = new StringBuilder();
                //m = new StringBuilder(newstr.Substring(indexI));
                m = new StringBuilder (newstr).Remove(0, indexI);
                //此"i"位置后所有"n"的个数
                count += ( from c in m.ToString() where c == 'n' select c).Count();
                //去掉当前"i"
                //newstr = newstr.Remove(indexI, 1);
                n = new StringBuilder (newstr).Remove(indexI, 1);
                newstr = n.ToString();
                m.Clear();
                n.Clear();
                //递归
                getCount(oldstr, newstr, ref count);
            }
            else
            {
                if (oldstr.IndexOf('i' ) > 0 && oldstr.Length >= 4)
                {
                    //b...g,找到字符串末端第2个"g"字符递归
                    oldstr = oldstr.Remove(oldstr.Length - 1, 1).TrimEnd( new char [] { 'i', 'n', 'b' });
                    newstr = oldstr;
                    getCount(oldstr, newstr, ref count);
                }
            }
        }


        static void Main(string[] args)
        {
            int n = 0, count = 0, totalCount = 0;
            string[] bing = new [] { "b", "i", "n" , "g" };
            StringBuilder bingStringBuilder = new StringBuilder();
            Random r = new Random();
            for (int i = 0; i < 10000; i++)
            {
                n = r.Next(0, 4);
                bingStringBuilder = bingStringBuilder.Append(bing[n]);
            }
            //创建只包含字符‘b’、‘i’、‘n’、‘g’且长度不超过10000的字符串
            string bingStr = bingStringBuilder.ToString();
            //去掉首尾不能组合成bing的字符即b......g
            bingStr = bingStr.TrimStart( new char [] { 'i', 'n', 'g' }).TrimEnd( new char [] { 'i', 'n', 'b' });


            while ((from c in bingStr where c == 'b' select c).Count() != 0)
            {
                //b......g格式下bing个数
                getCount(bingStr, bingStr, ref count);
                totalCount += count;
                //去掉字符"b"
                bingStr = bingStr.Remove(0, 1);
                //b......g,确定下一个"b"字符
                bingStr = bingStr.TrimStart( new char [] { 'i', 'n', 'g' });
                count = 0;
            }
            Console.WriteLine("包含字符‘b’、‘i’、‘n’、‘g’且长度不超过10000的字符串为:" + bingStringBuilder);
            Console.WriteLine();
            Console.WriteLine("组合成单词\"bing\"的个数:" + totalCount);
            Console.WriteLine();
            Console.WriteLine("输出对10^9 + 7取余数之后的结果:" + totalCount % 1000000007 );
            Console.ReadLine();
        }
    }
}
方法二:当字符串长度为10000时运行超时(整个下来会非常耗时,用Stopwatch测了下差不多要8分钟)改为1000了,对10^9 + 7取余数之后的结果(悲催的写成1000000007 % totalCount了)挑战失败!
using System;
using System.Collections;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
/// <summary>
/// 解题思路:
/// 一、创建只包含字符‘b’、‘i’、‘n’、‘g’且长度不超过10000的字符串bingStr,用两个数据集合iList与gList记录下字符"i","g"的所在位置
/// 二、遍历iList集合,记录字符"i"前字符"b"的个数;在遍历中嵌套循环gList集合,记录字符"i"与字符"g"间字符"n"的个数。两者相乘累加即为所求
/// </summary>
public class Test 
{
   public static  int howmany(string s)
    {
        return 0;
    }
    //start 提示:自动阅卷起始唯一标识,请勿删除或增加。 
    public static void Main()
    {
        int n = 0;
        long totalCount = 0;
        string[] bing = new[] { "b", "i", "n", "g" };
        StringBuilder bingStringBuilder = new StringBuilder();
        List<int> iList = new List<int>();
        List<int> gList = new List<int>();
        Random r = new Random();
        for (int i = 0; i < 1000; i++)
        {
            n = r.Next(0, 4);
            bingStringBuilder = bingStringBuilder.Append(bing[n]);
            if (bing[n] == "i")
            {
                iList.Add(i);
            }
            if (bing[n] == "g")
            {
                gList.Add(i);
            }
        }
        //创建只包含字符‘b’、‘i’、‘n’、‘g’且长度不超过10000的字符串
        string bingStr = bingStringBuilder.ToString();
        foreach (int i in iList)
        {
            //当前字符"i"前的字符串子串
            string bingStrLeft = bingStr.Substring(0, i);
            //当前字符"i"前字符"b"的个数
            //int bCount = (from c in bingStrLeft where c == 'b' select c).Count();
            int bCount = bingStrLeft.Replace("i", "").Replace("n", "").Replace("g", "").Length;
            if (bCount > 0)
            {
                foreach (int g in gList)
                {
                    //字符"i"在字符"g"前
                    if (g > i)
                    {
                        //当前字符"i"后字符"g"前(不包含字符"g")的字符串子串
                        string subBingStr = bingStr.Substring(i, g - i);
                        //此字符串间字符"n"的个数
                        //int nCount = (from c in subBingStr where c == 'n' select c).Count();
                        int nCount = subBingStr.Replace("b", "").Replace("i", "").Replace("g", "").Length;
                        //字符"i"字符"g"固定时所能组成"bing"的总个数
                        totalCount += bCount * nCount;
                    }
                }
            }
        }
        Console.WriteLine("包含字符‘b’、‘i’、‘n’、‘g’且长度不超过10000(实际长度为1000)的字符串为:" + bingStr);
        Console.WriteLine();
        Console.WriteLine("组合成单词\"bing\"的个数:" + totalCount);
        Console.WriteLine();
        Console.WriteLine("输出对10^9 + 7取余数之后的结果:" + (totalCount == 0 ? 0 : (totalCount % 1000000007)));
    }
    //end //提示:自动阅卷结束唯一标识,请勿删除或增加。
}




你可能感兴趣的:(编程,英雄会,几个bing)