[NOIP提高组2001]统计单词个数

问题描述:
给出一个字符串,要求分成k段,每段包含给定单词的数目尽量多,求最多包含几个单词
题解:
这道题还是有点难想的,
f[i][j]表示1到i分成j段的最多单词数,f[i][j]=max(f[i][j],f[k][j-1]+a[k+1][i])
其中a[i][j]表示i到j中包含的单词数。这个可以暴力搞。

#include
#include
#include
#include
#include
using namespace std;
int n,p,m;
char s[300],word[20][210];
int sa[300][300];//从i到j之间有几个单词 
bool tf[300];
int f[300][300];//从1到i,切成j段的最多单词数 
int main()
{
    scanf("%d%d",&n,&p);
    for(int i=0;iscanf("%s",s+i*20+1);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",word[i]);
        for(int j=1;jif(!strcmp(word[i],word[j])) {i--;m--;break;}//去重 
    }
    //暴力求sa
    for(int i=1;i<=n*20;i++)
    for(int j=1;j<=n*20;j++)
    {
        memset(tf,0,sizeof(tf));
        for(int k=1;k<=m;k++)
        {
            int len=strlen(word[k]);
            for(int u=i;u<=j-len+1;u++)
            {
                if(tf[u]) continue;
                int flag=0;
                for(int v=0;vif(s[u+v]!=word[k][v]){flag=1;break;}
                if(flag==0){sa[i][j]++;tf[u]=1;}
            }
        }
     } 
     //DP
     for(int k=1;k<=p;k++)
     for(int i=1;i<=20*n;i++)
     {
        for(int j=k-1;j<=i-1;j++)
        {
            f[i][k]=max(f[i][k],f[j][k-1]+sa[j+1][i]);
         }
      } 
      printf("%d\n",f[20*n][p]);
}

你可能感兴趣的:(DP,历年noip)