洛谷 P1246 编码 递推+字符串

原文链接: https://www.luogu.org/blog/hypercubestudio/solution-p1246

思路来自于ICE_Wol,如果侵权,请联系删除

题目描述
编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数宇。

字母表中共有26个字母{a,b,…,z},这些特殊的单词长度不超过6且字母按升序排列。把所有这样的单词放在一起,按字典顺序排列,一个单词的编码就对应着它在字典中的位置。

例如:

a→1 b→2 z→26 ab→27 ac→28

你的任务就是对于所给的单词,求出它的编码。

输入格式
仅一行,被编码的单词。

输出格式
仅一行,对应的编码。如果单词不在字母表中,输出0。

输入输出样例
输入 #1
ab
输出 #1
27

解法:递推+字符串

我们开一个数组f[i][j]表示以i开头长度为j的字符串的数量,所以我们可以得到以下递推式

f[i][j]=f[i+1][j−1]+f[i+2][j−1]+f[i+3][j−1]+…+f[z][j−1]

把上面的i用i+1代替可得到下面式子

f[i+1][j]=f[i+2][j−1]+f[i+3][j−1]+…+f[z][j−1]

再把这个式子代入最开始的那个式子,我们就可以得到

f[i][j]=f[i+1][j−1]+f[i+1][j]

然后就直接通过递推可得到这个数组,最后把符合的加入到ans里即可

AC代码

#include<iostream>
#define re register int
using namespace std;
string s;
int ans,cnt,f[30][10];
int main() {
	cin>>s;
	for(re i=1;i<s.length();i++) {
		if(s[i-1]>=s[i]) {
			cout<<0;
			return 0;
		}
	}
	for(re i=1;i<=26;i++) f[i][1]=1;
	for(re j=2;j<=6;j++) {
		for(re i=27-j;i>=0;i--) {
			f[i][j]=f[i+1][j-1]+f[i+1][j];
		}
	}
	for(re j=s.length()-1;j>=0;j--) {
		cnt++;
		for(re i=1;i<=s[j]-'a'+1;i++) {
			ans+=f[i][cnt];
		}
	}
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44343213/article/details/102747291