NOIP洛谷刷题-P1026 统计单词个数

2018年信息学奥赛NOIP资料下载
题目链接:https://www.luogu.org/problemnew/solution/P1026

思路:暴力预处理区间[l,r]的单词数,l,r∈[1,len]\wedgel<=r,然后dp[i][k]表示到第i个位置分成k块的最大单词数

转移方程:dp[i][k]=max(dp[i][k],dp[j][k-1]+num[j+1][1]) j∈[1,i]

参考代码:

#include<bits/stdc++.h>
using namespace std;
 
int m;
string s,dic[10],ch;
int num[205][205],dp[205][45];
 
 
bool judge(int l,int r)
{
    string ss=s.substr(l,r-l+1);//取出l到r的字符串
    for(int i=1;i<=m;i++)
        if(ss.find(dic[i])==0)return true;//find返回的是第一个下标
    return false;
}
 
int main()
{
    ios::sync_with_stdio(false);
    int p,k;
    cin>>p>>k;
    s+='\0';//为了s的下标从1开始
    for(int i=1;i<=p;i++)
    {
        cin>>ch; 
        s+=ch;
    }
    cin>>m;
    for(int i=1;i<=m;i++)
        cin>>dic[i];
    int len=s.length()-1;
    for(int i=len;i>=1;i--)//预处理单词数,i为右端点,j为左端点
    {
        for(int j=i;j>=1;j--)
        {
            num[j][i]=num[j+1][i];
            if(judge(j,i))num[j][i]++;
        }
    }
    dp[0][0]=0;
    for(int i=1;i<=len;i++)//边界状态,到i只分成一块即1-i的单词数
        dp[i][1]=num[1][i];
    for(int i=1;i<=len;i++)//枚举右端点,左端点都是max(1,分的段数)
        for(int j=1;j<=k&&j<=i;j++)//枚举分成了几段
            for(int l=j;l<i;l++)//枚举左端点与右端点之间的点
                dp[i][j]=max(dp[i][j],dp[l][j-1]+num[l+1][i]);
    printf("%d\n",dp[len][k]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值