洛谷 P1026 统计单词个数(字符串+DP)

题目链接: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\n",f[len][k]);
35     return 0;
36 }
AC代码

 

posted @ 2020-11-02 20:31  dfydn  阅读(148)  评论(0编辑  收藏  举报