题目链接:https://www.luogu.com.cn/problem/P1026
关于字符串的函数:
1. s.substr(x,len) 在s中取出从x位置开始,长度为len的字符串,并返回string类型的字符串。
2. s.find(a) 在s中查找字符串a,并返回起始下标(从0开始),若不存在,返回1844674407370955161,即(1999999999999999)16.
首先这道题注意关于字符串函数的使用。
设f[i][j]表示前i个字符划分成了j块时的最大个数。 sum[i][j]表示从第i个位置到第j个位置有多少个单词。
初始化。
转移的时候枚举断点l:
$f[i][j]=max(f[l][j-1]+sum[l+1][i])$
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 string s,a[7]; 5 int n,p,k; 6 int sum[805][805],f[805][805]; 7 bool check(int l,int r){ 8 string x=s.substr(l,r-l+1); 9 for(int i=1;i<=n;i++) if(x.find(a[i])==0) return 1; 10 return 0; 11 } 12 int main(){ 13 s+='0'; 14 scanf("%d%d",&p,&k); 15 for(int i=1;i<=p;i++){ 16 string ch; 17 cin>>ch; 18 s+=ch; 19 } 20 scanf("%d",&n); 21 int len=s.length()-1; 22 for(int i=1;i<=n;i++) cin>>a[i]; 23 for(int j=len;j>=1;j--) 24 for(int i=j;i>=1;i--){ 25 sum[i][j]+=sum[i+1][j]; 26 if(check(i,j)) sum[i][j]++; 27 } 28 f[0][0]=0; 29 for(int i=1;i<=k;i++) f[i][i]=f[i-1][i-1]+sum[i][i]; 30 for(int i=1;i<=len;i++) f[i][1]=sum[1][i]; 31 for(int i=1;i<=len;i++) 32 for(int j=1;j<=k&&j<i;j++) 33 for(int l=j;l<i;l++) f[i][j]=max(f[i][j],f[l][j-1]+sum[l+1][i]); 34 printf("%d ",f[len][k]); 35 return 0; 36 }