P1026 [Groupe d'amélioration NOIP2001] Comptez le nombre de mots

description du sujet

Donnez une chaîne de lettres composée de lettres anglaises minuscules dont la longueur ne dépasse pas 200 (la chaîne est saisie sous la forme de 20 lettres par ligne, et il est garanti que chaque ligne doit être de 20). Il est nécessaire de diviser cette chaîne de lettres en k parties, et le nombre total de mots contenus dans chaque partie est le plus grand.

Les mots contenus dans chaque exemplaire peuvent se chevaucher partiellement. Lorsqu'un mot est sélectionné, sa première lettre ne peut plus être utilisée. Par exemple,   and  this peut être inclus dans  la chaîne  mais ne peut pas être inclus après  la sélection .thisisthisth

Mots dans un dictionnaire donné de 6 mots maximum.

Il est nécessaire d'afficher le nombre maximum.

format d'entrée

La première ligne de chaque groupe comporte deux entiers positifs p,k. p représente le nombre de lignes dans la chaîne et k représente la division en k parties.

Les p lignes suivantes comportent chacune 20 caractères.

Il y a ensuite un entier positif s, indiquant le nombre de mots dans le dictionnaire. Les lignes suivantes contiennent chacune un mot.

format de sortie

1 entier, correspondant aux résultats correspondants de chaque ensemble de données de test.

Exemples d'entrée et de sortie

Tapez #1 pour copier

1 3 
ceci est un livre dans ta région oh 
4 
est 
un 
ok 
sab

copie de la sortie n°1

7

Analyser :

Le titre doit être lu clairement : lorsque la première lettre est utilisée, elle ne sera pas utilisée.

Deuxièmement, il est divisé en k parts.

En regardant l'entrée et la sortie.

n indique qu'il y a n lignes et chaque ligne est une chaîne de longueur 20.

On peut juger de l'arrière vers l'avant le nombre que peut contenir la première chaîne.

Gourmand : autant de mots que possible, divisés en une chaîne.

Dans le cas d'une dérivation récursive de chaque division de bas en haut.

Le code est visible :

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int n, m,len,k;
string st, ch, a[45];
int sum[210][210];
int dp[210][45];
bool check(int l, int r) {
	string ss = st.substr(l, r - l + 1);
	for (int i = 0; i < m; i++) {
		if (ss.find(a[i]) == 0) { //等于 0 表示 为头个字母被用了 + 1
			return 1;
		}
	}
	return 0;
}
void word() {
	dp[0][0] = 0; // i 表示从字符的长度,j表示划分了 j次
	for (int i = 1; i <= k; i++) {
		dp[i][i] = dp[i - 1][i - 1] + sum[i][i];
	}
	for (int i = 1; i <= len; i++) {
		dp[i][1] = sum[1][i];
	}
	for (int i = 1; i <= len; i++) {
		for (int j = 1; j <= k && j < i; j++) {// 如 aaa 可以划分的个数 为 长度 -1
			for (int l = j; l < i; l++) {// 表示从间隙为 j 的字符开始  比如 aaaa j = 2 是 前面的长度用从 l = 2 开始,此时前面划分了 1 个 在从 l 开始划分二个。
				dp[i][j] = max(dp[i][j], dp[l][j - 1] + sum[l + 1][i]);
			}
		}
	}
}
void slove() {
	cin >> n >> k;
	st += '0';
	for (int i = 1; i <= n; i++) {
		cin >> ch;
		st += ch;
	}
	cin >> m;// 单词的个数
	for (int i = 0; i < m; i++) {
		cin >> a[i];
	}
	len = st.size() - 1; 
	for (int i = len; i >= 1; i--) { // 从 j ~ i
		for (int j = i; j >= 1; j--) {
			sum[j][i] = sum[j + 1][i];  
			if (check(j, i)) {
				sum[j][i]++;
			}
		}
	}
	word();
	cout << dp[len][k];
}
int main() {
	slove();
	return 0;
}

Je suppose que tu aimes

Origine blog.csdn.net/zhi6fui/article/details/129907579
conseillé
Classement