《单词解密》递归解法
(整理原始题解.jpg)
题目链接很细节的一道题,交了好几次才过。
本题的对于字符的理解(匹配)很明显不具备后效性 ,所以考虑递归(推)。
设计递归要素:(我的枚举顺序 为从前向后)
对于每一个字符,无非有以下可能:
(1)该字符为 0 0 0,匹配失败(没有对应的字符);
(2)不满足(1),该字符不是字符串中最后一位且该字符与下一位字符组合结果小于等于 26 26 26,于是这两位字符就匹配成功;
(3)不满足(1)且下一位不是 0 0 0,这一位字符单独匹配。
递归边界:当字符串枚举完毕时,返回 1 1 1种可能(当然程序中为了方便实现+防止越界,边界有所变动)。
注意事项:也许有人会细心注意到(1)和(3)判断条件可能重复,(1)永远也不会发生,但是当第一位就是 0 0 0时,(1)就能发挥作用;另外需要加记忆化,而且数组需要清 − 1 -1 −1,(因为记忆化数组的值可能为 0 0 0),  v h [ i ] vh[i] vh[i] 表示从第  i i i 位到最后一位的可能性取模。
利用乘法原理将可能性乘起来,再利用余数定理取模,最后输出。因为已经有人发过dp解法了,本蒟蒻就不献丑转递推了。
在结尾,希望各位如果发现了题解的不足之处,还请指正,谢谢!
#include <bits/stdc++.h>
#define int long long
using namespace std;
int num,vh[300010];
string s;
int f(int pos){
	if(vh[pos]!=-1)return vh[pos];
	if(pos==num-1){
		if(s[pos]=='0')return vh[pos]=0;
		return vh[pos]=1;
	}
	if(pos==num-2){
		if(s[pos]=='0')return vh[pos]=0;
		if((s[pos]-'0')*10+s[pos+1]-'0'<=26){
			if(s[pos+1]=='0')return vh[pos]=1;
			return vh[pos]=2;
		}
		if(s[pos+1]=='0')return vh[pos]=0;
		return vh[pos]=1;
	}
	if(s[pos]=='0')return vh[pos]=0;
	if((s[pos]-'0')*10+s[pos+1]-'0'<=26){
		if(s[pos+1]=='0')return vh[pos]=f(pos+2)%1000000007;
		return vh[pos]=(f(pos+1)+f(pos+2))%1000000007;
	}
	if(s[pos+1]=='0')return vh[pos]=0;
	return vh[pos]=(f(pos+1))%1000000007;
}
signed main(){
	memset(vh,-1,sizeof(vh));
	cin>>s;
	num=s.size();
	cout<<f(0)<<endl;
	return 0;
}
// cb0e6e9a-dd37-4236-9903-57438d60651e

                
            
        
浙公网安备 33010602011771号