P1026 统计单词个数

 

链接: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
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

 

 

 

你可能感兴趣的:(dp)