动态规划dp--单词分割权重

        今日遇到一个很适合用来学习动态规划的题目,记录一下做法。

        题目:有一个词典,词典中有单词,每个单词有一个权重。输入一个字符串,将字符串根据词典划分为一个个“单词”,对应的权重为每个单词的权重和。如词典中:abcdefg,根据词典划分,/abc/de/fg,权重为abc、de和fg的权重之和。要求输出权重最大的一种分割结果。

        (这里我将词典写到代码中,也可以自己构建。)输入是一串字符串。


分析:dp[i]表示前i个字符的最大权重和。

dp[0]=0,dp[i]=max(dp[j-1]+(j-1到i的子字符串权重)),其中j从1到i,i从1到n。


#include <stdio.h>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

  using namespace std;

  // 定义词典,每个单词对应一个权重
  unordered_map<string, int> dictionary = {
      {"a", 3},
      {"b",2},
      {"bos", 2},
      {"os",4},
      {"s",10},
      //{"bo",1}
      // 添加其他单词和权重
  };

  // 计算字符串的权重
  int calculateWeight(const string& str) {
    if (dictionary.find(str) != dictionary.end()) {
      return dictionary[str];
    }
    return 0; // 如果词典中没有对应单词,则权重为0
  }


  // 动态规划函数,返回权重最大的分割方法
  string maximizeWeight(const string& input) {
    int n = input.length();//输入单词长度
    vector<int> dp(n + 1, 0);  // dp[i]表示前i个字符的最大权重和
    vector<string> result(n + 1, "");//对应位置存放分割的子字符串

    for (int i = 1; i <=  n; i++) {
      for (int j = 1; j <= i; j++) {
        if(dp[j-1]==-1) {
          continue;//前j-1个字符串中有找不到的,那就跳过
        }
        string word = input.substr(j - 1, i - (j - 1));//从j-1到i的子字符串
        int currentWeight = calculateWeight(word);
        //更新dp[i]
        if (currentWeight > 0 && dp[j-1] + currentWeight > dp[i]) {
          dp[i] = dp[j-1] + currentWeight;
          result[i] = word;
        }
      }
      if(dp[i]==0)dp[i]=-1;//如果子字符串中一直有找不到的单词,dp为-1

    }

    for(auto dp:dp)cout<<dp<<",";
    if(dp[n] == -1)return "-1";

    // 从结果中回溯以找到最大权重和的分割方法
    string segmentedInput;
    int currentIndex = n;
    while (currentIndex > 0) {
      segmentedInput = result[currentIndex] + "\\" + segmentedInput;
      currentIndex -= result[currentIndex].length();
    }

    return "\\"+segmentedInput;
  }

  int main() {
    string input;
    cout << "请输入字符串: ";
    cin >> input;
    string segmentedString = maximizeWeight(input);
    cout << "权重最大的分割方法为: " << segmentedString << endl;
    return 0;
  }

结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XiangrongZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值