提交时间:2026-07-17 12:35:46
运行 ID: 92672
#include<bits/stdc++.h> using namespace std; const int N=200,K=40; int p,k,n,m,dp[N+5][K+5],ans[N+5][N+5]; string s,a[10]; void init(){ bool vis[N+5]={}; for(int i=1;i<=m;i++){ memset(vis,0,sizeof(vis)); //每次开一个新区间都要把标记清空 for(int j=i;j<=m;j++){ ans[i][j]=ans[i][j-1]; //先加上上一区间答案 for(int x=1;x<=n;x++){ //枚举每个单词来匹配 if(i+a[x].size()-1>j) continue; //长度比单词都短,肯定没戏 bool flag=0; for(int y=0;y<a[x].size();y++){ if(s[j-y]!=a[x][a[x].size()-y-1]) flag=1; //这里是逆向匹配 } if(!flag){ int beg=j-a[x].size()+1; if(!vis[beg]) ans[i][j]++,vis[beg]=1; //注意vis标记 } } } } } int main(){ cin>>p>>k; k--; //注意是k段,切k-1次 for(int i=1;i<=p;i++){ string w; cin>>w; s+=w; } m=s.size(); s=" "+s; //先给字符串偏移一下,对好下标 cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; init(); //预处理ans[i][j] for(int i=1;i<=m;i++) dp[i][0]=ans[1][i]; for(int j=1;j<=k;j++){ for(int i=1;i<=m;i++){ for(int x=j;x<i;x++){ dp[i][j]=max(dp[i][j],dp[x][j-1]+ans[x+1][i]); } } } cout<<dp[m][k]; return 0; }