SOJ 1001

1001. Alphacode

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Alice and Bob need to send secret messages to each other and are discussing ways to encode their messages: Alice: "Let's just use a very simple code: We'll assign `A' the code word 1, `B' will be 2, and so on down to `Z' being assigned 26." Bob: "That's a stupid code, Alice. Suppose I send you the word `BEAN' encoded as 25114. You could decode that in many different ways!" Alice: "Sure you could, but what words would you get? Other than `BEAN', you'd get `BEAAD', `YAAD', `YAN', `YKD' and `BEKD'. I think you would be able to figure out the correct decoding. And why would you send me the word `BEAN' anyway?" Bob: "OK, maybe that's a bad example, but I bet you that if you got a string of length 500 there would be tons of different decodings and with that many you would find at least two different ones that would make sense." Alice: "How many different decodings?" Bob: "Jillions!" For some reason, Alice is still unconvinced by Bob's argument, so she requires a program that will determine how many decodings there can be for a given string using her code.

Input

Input will consist of multiple input sets. Each set will consist of a single line of digits representing a valid encryption (for example, no line will begin with a 0). There will be no spaces between the digits. An input line of `0' will terminate the input and should not be processed

Output

For each input set, output the number of possible decodings for the input string. All answers will be within the range of a long

Sample Input

25114
1111111111
3333333333
0

Sample Output

6
89
1
这题主要思路是递归,设递归函数f(string A,int low,int high),此函数的返回值为字符串A下标从low到high这段的解码种数,所以对于25114,解码第一个字母可以是B(2),则第一个字母为B的种数共为f(A,1, 4),或者第一个字母为Y(25),则第一个字母为Y的种数共为f(A,2,4),所以总种数为f(A,0,4)=f(A,1,4)+f(A,2,4),以此进行递归,终止情况为low>=high时,此时f(A,low,high)=1。
  但并不是每次字母都有两种选择,所以在递归式中要注意分类,尤其要注意0的位置。


if 若下标low+1为0,且下标为low的数字小于3,则首字母只有一种情况所以返回f(A,low+1,high)。
else if 若下标low+1为0,且下标为low的数字大于3,则无对应编码,所以返回0;
else if 若high-low>=2,即至少有三位数字,若low+2为0,则首字母只有一种情况,所以返回f(A,low+1,high)。
else if 若前两个数字小于27,则首字母有两种情况,所以返回f(A,low+1,high)+f(A,low+2,high);
else 若以上分类都不满足,则首字母只有一种情况,返回f(A,low+1,high)。
  然而这样递归调用非常耗费时间,尤其是有非常多的重复计算,所以想办法消除重复的计算以提高效率。所以可以考虑设置一个数组来保存递归函数的值,不妨设置一个int类型的memory数组,每次计算前先将其置为0。memory【low】保存f(A,low,high)的值,当递归调用时先判断memory【low】是否为0,若为0则代表是第一次计算这一函数的值,则进行递归,若memory【low】不为0,则代表此函数的值已经经过计算且保存在了数组中,则直接返回memory【low】。

  PS:这题还有个非常坑的地方,题目描述中没有说明输入的数字字符串会有多长,所以我起初将memory数组的大小设为了100,却一直都是WA,改到精神崩溃都没有通过,后来百度其他人的代码,偶然注意到了这个问题,把100改成了1000001才通过。

// Problem#: 1001
// Submission#: 4824098
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include 
#include 

#include 

using namespace std;
vector memory(1000001,0);
void ini()
{
    for(vector::iterator iter = memory.begin(); iter!=memory.end();++iter)
    {

    *iter = 0;
    }
}

long f(string &A,int low,int high)

{
    
    if(memory[low]==0)
    
    {
    

      if(low>=high)
      memory[low]=(long)1;



else if (A.at(low+1)=='0'&&A.at(low)<'3')
   memory[low]=f(A,low+2,high);
else if(A.at(low+1)=='0'&&A.at(low)>='3')
memory[low]=(long)0;
else if(high-low>=2&&A.at(low+2)=='0'&&A.at(low+1)<'3')

 memory[low]=f(A,low+1,high);
else if(high-low>=2&&A.at(low+2)=='0'&&A.at(low+1)>='3')
memory[low]=(long)0;



else if (A.substr(low,2)<"27")
 memory[low]=f(A,low+1,high)+f(A,low+2,high);

else  memory[low]=f(A,low+1,high);

} 
return memory[low];
}




int main()

{


string code;


  while(cin>>code&&code!="0")
{

   
ini();
cout<


你可能感兴趣的:(SOJ)