Google Code Jam 2009预选赛第三题----Welcome to Code Jam

来源:互联网 发布:1万淘宝买家数据购买 编辑:程序博客网 时间:2024/04/29 04:23

http://code.google.com/codejam/contest/dashboard?c=90101#s=p2

 

So you've registered. We sent you a welcoming email, to welcome you to code jam. But it's possible that you still don't feel welcomed to code jam. That's why we decided to name a problem "welcome to code jam." After solving this problem, we hope that you'll feel very welcome. Very welcome, that is, to code jam.

If you read the previous paragraph, you're probably wondering why it's there. But if you read it very carefully, you might notice that we have written the words "welcome to code jam" several times: 400263727 times in total. After all, it's easy to look through the paragraph and find a 'w'; then find an 'e' later in the paragraph; then find an 'l' after that, and so on. Your task is to write a program that can take any text and print out how many times that text contains the phrase "welcome to code jam".

To be more precise, given a text string, you are to determine how many times the string "welcome to code jam" appears as a sub-sequence of that string. In other words, find a sequence s of increasing indices into the input string such that the concatenation of input[s[0]], input[s[1]], ..., input[s[18]] is the string "welcome to code jam".

The result of your calculation might be huge, so for convenience we would only like you to find the last 4 digits.

Input

The first line of input gives the number of test cases, N. The next N lines of input contain one test case each. Each test case is a single line of text, containing only lower-case letters and spaces. No line will start with a space, and no line will end with a space.

Output

For each test case, "Case #x: dddd", where x is the case number, and dddd is the last four digits of the answer. If the answer has fewer than 4 digits, please add zeroes at the front of your answer to make it exactly 4 digits long.

Limits

1 ≤ N ≤ 100

Small dataset

Each line will be no longer than 30 characters.

Large dataset

Each line will be no longer than 500 characters.

 

这个题目我是用动态规划算法来解决的,假设待测试字符串为str1, "welcome to code jam"为str2

状态转移方程是

F(i,j)=F(i+1, j+1)+F(i+1, j) 当str1[i]==str2[j]

       =F(i+1, j)                    当str1[i]!=str2[j]

其中第一个参数表示待测试字符串当前匹配字符的位置.

      第二个参数表示"welcome to code jam"的当前匹配字符的位置.

计算的是F(0,0)结束条件是i==strlen(str1)||j==strlen(str2)

 

当然,这个题目不能用递归,否则效率上估计不行, 构造一张strlen(str1)*strlen(str2)的表,来填充是比较科学的.

同时如果把每个字符都重复一遍作为测试字符串,既"wweellccoo......", 那么结果应该是2^19, 如果重复的更多,会更大,所以肯定是要用大数来保存结果的, 而题目只要求输出最后的4位十进制数, 所以相对简单一些.

 

在写代码中,为了方便, 我用一个int来表示最后的4位数, 既每个BYTE表示一位.

 

代码如下:

#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define MAX_LENGTH (512)

int Add(int x, int y)
{
 int nRet = x + y;
 int nVal1 = nRet&0xFF;
 int nVal2 = (nRet>>8)&0xFF;
 int nVal3 = (nRet>>16)&0xFF;
 int nVal4 = (nRet>>24)&0xFF;
 if(nVal1>=10)
 {
  nVal2 += nVal1/10;
  nVal1%=10;
 }
 if(nVal2>=10)
 {
  nVal3 += nVal2/10;
  nVal2%=10;
 }
 if(nVal3>=10)
 {
  nVal4 += nVal3/10;
  nVal3%=10;
 }
 if(nVal4>=10)
 {
  nVal4%=10;
 }
 return nVal1+(nVal2<<8)+(nVal3<<16)+(nVal4<<24);
}

int main()
{
 char pStr[MAX_LENGTH];
 char *pMatch = "welcome to code jam";

 FILE* fp;
 int nRound;
 int i, j, k;
 fp = fopen("1.txt", "r");
 fscanf(fp, "%d", &nRound);
 int nLenMatch = strlen(pMatch);
 int nLenStr;

 int* pCal = (int*)malloc(MAX_LENGTH*nLenMatch*sizeof(int));
 int* pCalTmp;
 fgetc(fp);
 for(i=0; i<nRound; i++)
 {

  for(j=0; j<MAX_LENGTH; j++)
  {
   int ch = fgetc(fp);
   if(ch == '/n') break;
   pStr[j] = ch;
  }
  nLenStr = j;
  pCalTmp = pCal+nLenMatch*nLenStr-1;
  
  if(pStr[nLenStr-1]==pMatch[nLenMatch-1])
   *pCalTmp--=1;
  else
   *pCalTmp--=0;
  for(k=nLenStr-2; k>=0; k--, pCalTmp--)
  {
   if(pStr[k]==pMatch[nLenMatch-1])
   {
    *pCalTmp = Add(*(pCalTmp+1), 1);
   }
   else
   {
    *pCalTmp = *(pCalTmp+1);
   }
  }
  for(j=nLenMatch-2; j>=0; j--)
  {
   *pCalTmp--=0;
   for(k=nLenStr-2; k>=0; k--, pCalTmp--)
   {
    if(pStr[k]==pMatch[j])
    {
     *pCalTmp = Add(*(pCalTmp+1), *(pCalTmp+nLenStr));
    }
    else
    {
     *pCalTmp = *(pCalTmp+1);
    }
   }
  }
  int nRet = *pCal;
  printf("Case #%d: %d%d%d%d/n", i+1, (nRet>>24), (nRet>>16)&0xFF, (nRet>>8)&0xFF, nRet&0xFF);
 }
 return 0;
}

 

原创粉丝点击