洛谷 P1246 编码 题解
本题本质上是一个找规律填表(暨递推)的题目
思路非常明确,举一个简单的例子:
对于一个字符串“ade”,它的长度为3.
那么他在题设要求中的字符串编号可以用以下方式求解:
- 所有长度为1和2的字符串数量 + 所有开头为a,由bc到de的字符串数量;
- 所有开头为a,由bc到de的字符串数量就相当于所有开头为d长度为2的字符串数量加上开头为d长度为2直到末位是e的字符串数量;
由以上例子第二条我们可以类比其他情况,得到这样一个表格
P.S.你可以在Excel中很轻松地制作出这个表格
在该表格中,横行表示开头字母,纵行表示字串长度,表格中的数据以该字母开头的该长度字符串的总数
对于任何一群以i开头,长度为j的字符串,它的数量均为可以以这样一个公式表示:
\(f[i][j] = f[i + 1][j - 1] + f[i + 2][j - 1] + f[i + 3][j - 1] + … + f[z][j - 1]\)
如果无法理解,没关系,我们再举一个例子
以a开头,长度为3的字符串数量如何计算?
这样的字符串有很多: abc acd ace ...
我们可以发现,这样的字符串的数量就相当于以b开头的长度为2的串的数量,加上以c开头长度为2的串的数量...一直到以y开头长度为2的串的数量,即为以上公式
(由于题设要求,没有以z开头长度为2的合法串)
但这样一个公式计算起来仍不方便,别急,我们再来看
由上面的公式,用i + 1替换i,我们可以得到这样一个式子
\(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]\)
用程序运行这个公式,计算数组f[i][j],就可以得到上述表格
而显然地,计算某个字符串的编号,就是计算字符串每一位在对应行从a到该位的值得和,说的比较抽象,举个例子就能理解
对于一个字符串“ade”:
从右至左,第一位是1,则第一行将a-e的数值相加
第二位是d,将第二行a-d的数值相加
以此类推,得到最终答案399.
至此,本题思路已分析完毕,接下来就是代码实现,需要注意一些细节的处理(数组下标一类),以下是完整代码
#include<iostream>
using namespace std;
string s;
int f[30][10],ans,cnt;
int main(){
cin >> s;
for(int i = 1;i < s.size();i++){
if(s[i - 1] >= s[i]){
cout << 0;
return 0;
}
}
//判断字符串是否合法(升序)
for(int i = 1;i <= 26;i++)
f[i][1] = 1;
//长度为1的字符串数量都是1
for(int j = 2;j <= 6;j++)
for(int i = 27 - j;i > 0;i--)
f[i][j] = f[i + 1][j - 1] + f[i + 1][j];
//由公式,我们从上至下从右至左进行计算
for(int j = s.size() - 1;j >= 0;j--){
cnt++;
for(int i = 1;i <= s[j] - 'a' + 1;i++)
ans += f[i][cnt];
}
//由以上的思路计算答案
cout << ans;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 用 C# 插值字符串处理器写一个 sscanf
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!