P1026 统计单词个数 [dp]
Posted Garen-Wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1026 统计单词个数 [dp]相关的知识,希望对你有一定的参考价值。
P1026 统计单词个数
这道题看上去就是要用dp的样子。裸裸的dp题无误。
首先要把分开的字符串合成那个长度小于等于\(200\)的总字符串。
然后做个预处理,预处理出任意区间内的单词个数,设为\(sum[i][j]\)。
有一个神奇的地方:
当选用一个单词之后,其第一个字母不能再用。
题解里面有这么一种解决方式:
倒序枚举\(j\)和\(i\)。初始化\(sum[i][j] = sum[i + 1][j]\)。如果子串中从一开始就存在单词,加1。
其实不怎么知道原理这种做法还刚好满足了上面的限制。
然后套上一种区间dp的思路,3重枚举更新dp。
因为若要分\(k\)段,则至少也要已经遍历过\(k\)个字符串,所以至少要从\(k\)开始。
代码:
/*************************************************************************
@Author: Garen
@Created Time : Tue 29 Jan 2019 09:56:30 PM CST
@File Name: P1026.cpp
@Description:
************************************************************************/
#include<bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
#define ll long long
const int maxn = 205;
string str;
string word[8];
int dp[maxn][maxn];
int pd[maxn];
int p, m, s, n;
int sum[maxn][maxn];
int check(int l, int r) {
l--; r--;
string ch = str.substr(l, r - l + 1);
for(int i = 1; i <= s; i++) {
if(ch.find(word[i]) == 0) return 1;
}
return 0;
}
int main() {
cin >> p >> m;
string temp;
while(p--) {
cin >> temp;
str = str + temp;
n += temp.length();
}
cin >> s;
for(int i = 1; i <= s; i++) cin >> word[i];
for(int j = n; j >= 1; j--) {
for(int i = j; i >= 1; i--) {
sum[i][j] = sum[i + 1][j] + check(i, j);
}
}
for(int i = 1; i <= m; i++) dp[i][i] = dp[i - 1][i - 1] + sum[i][i];
for(int i = 1; i <= n; i++) dp[i][1] = sum[1][i];
for(int i = 1; i <= n; i++) {
for(int j = 2; j <= m && j < i; j++) {
for(int k = j; k < i; k++) {
dp[i][j] = std::max(dp[i][j], dp[k][j - 1] + sum[k + 1][i]);
}
}
}
cout << dp[n][m] << endl;
return 0;
}
以上是关于P1026 统计单词个数 [dp]的主要内容,如果未能解决你的问题,请参考以下文章