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; }