P1026 统计单词个数

P1026 统计单词个数

设$f[i][j]$表示到主串第$i$位,已分成$j$段的最多单词数,$val[l][r]$表示区间$[l,r]$包含的单词个数

可得:$f[i][j]=max(f[i][j],f[u][j-1]+val[u+1][i])$

套一个三重循环即可

$val[l][r]$可以暴力处理

单词判重用map

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#define re register
using namespace std;
int max(int &a,int &b){return a>b?a:b;}
map<string,int> mp;
string a,b,c[8]; bool vis[202];
int p,k,n,m,f[202][42],len[8],val[202][202];
int main(){
    scanf("%d%d",&p,&k);
    for(int i=1;i<=p;++i) cin>>b,a=a+b,n+=b.size();
    scanf("%d",&m);
    for(int i=1;i<=m;++i){
        cin>>c[i];
        if(!mp[c[i]]) mp[c[i]]=1,len[i]=c[i].size();
        else --i,--m; //map判重
    }a.insert(0,"#");
    for(int i=1;i<=n;++i)
        for(int j=i;j<=n;++j){
            memset(vis,0,sizeof(vis));
            for(int k=1;k<=m;++k)
                for(int l=i;l+len[k]-1<=j;++l){
                    if(vis[l]) continue;
                    bool ok=1;
                    for(int r=1;r<=len[k];++r)
                        if(a[l+r-1]!=c[k][r-1])
                            {ok=0;break;}
                    if(ok) ++val[i][j],vis[l]=1;
                }
        }//暴力处理val数组
    for(int i=1;i<=k;++i)
        for(int j=1;j<=n;++j){
            for(int u=i-1;u<j;++u)
                f[j][i]=max(f[j][i],f[u][i-1]+val[u+1][j]);
        }
    printf("%d\n",f[n][k]);
    return 0;
}

 

posted @ 2018-10-19 18:44  kafuuchino  阅读(141)  评论(0编辑  收藏  举报