zoukankan      html  css  js  c++  java
  • Leetcode 115. 不同的子序列(二维DP)

    给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

    字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

    题目数据保证答案符合 32 位带符号整数范围。

    简单二维DP问题。设dp[i, j]表示以i结尾的子串含有t的长度为j的前缀的数量,二重循环遍历:

    (1)s[i] == t[j]: 转移方程为(dp[i][j] += dp[i - 1][j - 1] + dp[i - 1][j]),含义是当前可以由两种情况转移过来:

    ​ (a) s[i]恰好就是t[j],s中以i - 1为结尾的子串包括t的长度为j - 1的前缀的情况数。

    ​ (b)s中以i - 1为结尾的子串已经包括整个t的长度为j的前缀的情况数。

    (2)s[i] != t[j]: 转移方程为(dp[i][j] += dp[i - 1][j]),含义同上。

    初始化需要处理所有的dp[i, 1]为当前已经出现过的t[1]的数量。(代码中其实没必要开cnt数组存储)

    注意j初始化完了以后要从2开始,同时要开long long(虽然答案说范围在int32范围内)。还有一个坑点就是输入的字符串是大小写混合的。

    #include <iostream>
    using namespace std;
    long long dp[1005][1005];//dp[i][j]表示以i结尾的子串含有t的长度为j的前缀的数量
    long long cnt[100];
    int lens, lent;
    int main() {
    	memset(cnt, 0, sizeof(cnt));
    	memset(dp, 0, sizeof(dp));
    	string s, t;
    	cin >> s >> t;
    	lens = s.size(), lent = t.size();
    	s = " " + s, t = " " + t;
    	for(int i = 1; i <= lens; i++) {
    		cnt[s[i] - 'A']++;
    		dp[i][1] += cnt[t[1] - 'A'];
    	}
    	for(int i = 1;i <= lens; i++) {
    		for(int j = 2; j <= lent; j++) {//注意j初始化完了以后要从2开始
    			if(s[i] == t[j]) {
    				dp[i][j] += dp[i - 1][j - 1] + dp[i - 1][j];
    			} else {
    				dp[i][j] += dp[i - 1][j];
    			}
    		}
    	}
    	cout << dp[lens][lent];
    	return 0;
    }
    
  • 相关阅读:
    《深入V8引擎-第01课》
    《各 JavaScript 引擎的简介,及相关资料》
    《【前端性能】必须要掌握的原生JS实现JQuery》
    《[iOS][OC] 开发利器:控制器传送门VCPicker(附demo)》
    《iOS 上的 CSS 样式协议 VKCssProtocol》
    ICML 2019论文录取Top100:谷歌霸榜
    进阶!自然语言处理背后的数据科学
    学界!关于GAN的灵魂七问
    如何优化深度学习模型
    从DeepNet到HRNet,这有一份深度学习“人体姿势估计”全指南
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14550395.html
Copyright © 2011-2022 走看看