P1026 统计单词个数 【dp】

题目描述

给出一个长度不超过 200200 的由小写英文字母组成的字母串(该字串以每行 2020 个字母的方式输入,且保证每行一定为 2020 个)。要求将此字母串分成 kk 份,且每份中包含的单词个数加起来总数最大。

每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串 this 中可包含 this 和 is,选用 this 之后就不能包含 th

单词在给出的一个不超过 66 个单词的字典中。

要求输出最大的个数。

输入格式

每组的第一行有两个正整数 p,kp,k。 pp 表示字串的行数,kk 表示分为 kk 个部分。

接下来的 pp 行,每行均有 2020 个字符。

再接下来有一个正整数 ss,表示字典中单词个数。 接下来的 ss 行,每行均有一个单词。

输出格式

11个整数,分别对应每组测试数据的相应结果。

输入输出样例

输入 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
1 3
thisisabookyouareaoh
4
is
a
ok
sab
输出 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
7

 

 思路

  题意有个地方说的比较模糊,就是重叠的情况下的影响。

  实际上是用了this可以再选is,但是不能再选第一个字母t,也就是选满了main_len之后就不能选了。

  大概懂了之后就知道这是一个递推找字符串的子串里满足能在字典中找到单词且能出现几个单词。

  用 sum [ i ] [ j ] 来表示主字符串里 i ~ j 区间内有几个单词。

  用 f [ i ] [ j ] 来表示到第 i 个字符切成 j 段能获得的最大单词数。

  显然可以如下转移:

        f [ i ] [ k ] = max ( f [ i ] [ k ] , f [ j ] [ k - 1] + sum [ i - 1 ] [ j ] ) ; 其中 k ∈ [ 2, min ( k, j + 1 ) ] ;

 

CODE

 

 
#include  < bits/stdc++.h >
#define  dbg( x ) cout  <<  #x  <<  " = "  << x  << endl
#define  eps  1 e - 8
#define  pi  acos( - 1.0 )

using  namespace std ;
typedef  long  long LL ;

const  int inf  =  0x 3f3f3f3f ;

template < class T > inline  void  read(& res )
{
     char c ;T flag = 1 ;
     while((c = getchar()) < ' 0 ' ||c > ' 9 ' )if(c == ' - ' )flag =- 1 ;res =c - ' 0 ' ;
     while((c = getchar()) >= ' 0 ' &&c <= ' 9 ' )res =res * 10 +c - ' 0 ' ;res *=flag ;
}

namespace _buff  {
     const  size_t BUFF  =  1  <<  19 ;
     char  ibuf [BUFF ],  *ib  = ibuf ,  *ie  = ibuf ;
     char  getc()  {
         if  (ib  == ie )  {
            ib  = ibuf ;
            ie  = ibuf  +  fread(ibuf ,  1 , BUFF , stdin );
         }
         return ib  == ie  ?  - 1  :  *ib ++ ;
     }
}

int  qread()  {
     using  namespace _buff ;
     int ret  =  0 ;
     bool pos  =  true ;
     char c  =  getc();
     for  (;  (<  ' 0 '  || c  >  ' 9 ' )  && c  !=  ' - ' ; c  =  getc())  {
         assert( ~c );
     }
     if  (==  ' - ' )  {
        pos  =  false ;
        c  =  getc();
     }
     for  (; c  >=  ' 0 '  && c  <=  ' 9 ' ; c  =  getc())  {
        ret  =  (ret  <<  3 )  +  (ret  <<  1 )  +  (^  48 );
     }
     return pos  ? ret  :  -ret ;
}

int p , k ;

string a , b ;
string  ss [ 15 ];

int  sum [ 1000 ][ 1000 ];
int  f [ 1000 ][ 1000 ];

int  main()
{
     read(p );read(k );
     for  (  int i  =  1 ; i  <= p ;  ++)  {
        cin  >> b ;
        a  += b ;
     }
     int main_len  =  a .size();
     int n ;
     read(n );
    vector <int>  len(+  7 );
     for  (  int i  =  1 ; i  <= n ;  ++)  {
        cin  >>  ss [i ];
         len [i ]  =  ss [i ].size();
     }
     for  (  int i  =  0 ; i  < main_len ;  ++)  {
         for  (  int j  = i ; j  < main_len ;  ++)  { //todo:枚举子段
             for  (  int k  = i ; k  <= j ;  ++)  {
                 int ok  =  1 ;
                 for  (  int z  =  1 ; z  <= n ;  ++)  {
                     if(+  len [z ]  -  1  > j )
                         continue;
                     for  (  int w  =  0 ; w  <  len [z ];  ++)  {
                         if(==  len [z ]  -  1  &&  a [+ w ]  ==  ss [z ][w ])  {
                            ok  =  0 ;
                             break;
                         }
                         if( a [+ w ]  !=  ss [z ][w ])  {
                             break;
                         }
                     }
                     if( !ok )
                         break;
                 }
                 if( !ok )  {
                     sum [i ][j ] ++ ;
                 }
             }
         }
     }
    // for ( int i = 0; i < main_len; ++i ) {
    //     for ( int j = 0; j < main_len; ++j ) {
    //         printf("sum[%d][%d]:%d\n",i, j, sum[i][j]);
    //     }
    // }
     for  (  int i  =  0 ; i  < main_len ;  ++)  {
         f [i ][ 1 ]  =  sum [ 0 ][i ];
         for  (  int j  =  0 ; j  < i ;  ++)  {
             for  (  int k  =  2 ; k  <=  min(k , j  +  1 );  ++)  {
                 f [i ][k ]  =  max( f [i ][k ],  f [j ][-  1 ]  +  sum [+  1 ][i ]);
             }
         }
     }
    cout  <<  f [main_len  -  1 ][k ]  << endl ;
     return  0 ;
}
全部评论

相关推荐

诨号无敌鸭:恭喜佬,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务