HRBUST 1217 统计单词个数

$dp$。

设$dp[i][j]$为到$i$位置,切成了$j$段的最大收益,然后枚举一下$f$,$dp[i][j]=max(dp[f][j-1]+v[f+1][i])$。一段区间的价值可以用区间$dp$求得。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;

char s[300];
int p,k,len;
char h[10][30];
int x;
int dp[205][60], v[205][205];

bool check(int L,int R,int g)
{
    int p1=L,p2=0,Leng = strlen(h[g]);
    if(Leng>R-L+1) return 0;

    while(1)
    {
        if(p2==Leng) break;
        if(s[p1]!=h[g][p2]) return 0;
        p1++; p2++;
    }

    return 1;
}

int main()
{
    while(~scanf("%d%d",&p,&k))
    {
        memset(s,0,sizeof s);
        for(int i=1;i<=p;i++)
        {
            char t[30]; scanf("%s",t);
            strcat(s,t);
        }

        len=strlen(s);

        scanf("%d",&x);
        for(int i=1;i<=x;i++) scanf("%s",h[i]);

        memset(dp,0,sizeof dp);
        memset(v,0,sizeof v);

        for(int Len=1;Len<=len;Len++)
        {
            for(int st=0;st<len;st++)
            {
                int en = st+Len-1;
                if(en>=len) continue;

                for(int p=st;p<en;p++)
                    v[st][en] = max(v[st][en],v[st][p]+v[p+1][en]);

                for(int i=1;i<=x;i++)
                    if(check(st,en,i)) v[st][en] = max(v[st][en],v[st+1][en]+1);
            }
        }

        for(int i=0;i<len;i++) dp[i][1] = v[0][i];

        for(int j=2;j<=k;j++)
        {
            for(int i=j-1;i<len;i++)
            {
                for(int f=j-2;f<i;f++)
                {
                    dp[i][j]=max(dp[i][j],dp[f][j-1]+v[f+1][i]);
                }
            }
        }
        printf("%d
",dp[len-1][k]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/6518642.html