#(|模板|字符串算法+区间DP)P1026 统计单词个数(提高+/省选-)

题目描述

给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个)。要求将此字母串分成kk份(1<k \le 401<k40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串thisthis中可包含thisthis和isis,选用thisthis之后就不能包含thth)。

单词在给出的一个不超过66个单词的字典中。

要求输出最大的个数。

输入格式

每组的第一行有22个正整数(p,kp,k)

pp表示字串的行数,kk表示分为kk个部分。

接下来的pp行,每行均有2020个字符。

再接下来有11个正整数ss,表示字典中单词个数。(1 \le s \le 61s6)

接下来的ss行,每行均有11个单词。

输出格式

11个整数,分别对应每组测试数据的相应结果。

输入输出样例

输入 #1
1 3
thisisabookyouareaoh
4
is
a
ok
sab
输出 #1
7

说明/提示

this/isabookyoua/reaoh

预备知识:

c++中string类型的用法:

1.x.substr(a,len) 返回x字符串中下标从a开始,长度为len的字符串

2.s.lenth()计算s字符串的长度

3.s.find(a)在s字符串中寻找a字符串(也就是判断a是否是s的子串)若a是s的子串,则会返回a的首字母在s中的下标(因为s相当于是字符数组)

4.详细用法:https://blog.csdn.net/qq_37941471/article/details/82107077

https://www.cnblogs.com/Draymonder/p/6944479.html

https://blog.csdn.net/Alexander_1314/article/details/82192687

考虑思路:

设dp[i][j]表示从1->i分割成j段的最大单词个数

首先,预处理出原字符串任意两点间能统计的单词个数,然后以终点为阶段在最外层枚举,然后枚举次级阶段:分的段数,注意分段存在限制:段数小于等于字母个数,并且小于最大

允许分段数,最内层枚举断点,范围从1->i-1,进行区间dp

状态转移方程:dp[i][j]=max(dp[i][j],dp[k][j-1]+sum[k+1][i]);

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int p,k,m,n;
int dp[1200][1200];
int sum[1200][1200];
inline int read()
{
char ch;
while((ch=getchar())<'0'|| ch>'9');
int res=ch-48;
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-48;
return res;
}
string s,a[10];
bool check(int l,int r)
{
string x=s.substr(l,r-l+1);
for(int i=1;i<=n;i++)
if(x.find(a[i])==0)
return true;
return false;
}
void init()
{
p=read();
k=read();
string t;
s+='0';
for(int i=1;i<=p;i++)
{
cin>>t;
s+=t;
}
n=read();
m=s.length()-1;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=m;i>=1;i--)
for(int j=i;j>=1;j--)
{
sum[j][i]=sum[j+1][i];
if(check(j,i))
sum[j][i]++;
}
}
void work()
{
for(int i=1;i<=k;i++)
dp[i][i]=dp[i-1][i-1]+sum[i][i];
for(int i=1;i<=m;i++)
dp[i][1]=sum[1][i];
for(int i=1;i<=m;i++)
for(int j=1;j<=k&&j<=i;j++)
{
for(int q=j;q<i;q++)
dp[i][j]=max(dp[i][j],dp[q][j-1]+sum[q+1][i]);
}

cout<<dp[m][k];
}
int main()
{
init();
work();
return 0;
}

Guess you like

Origin www.cnblogs.com/little-cute-hjr/p/11423060.html