zoukankan      html  css  js  c++  java
  • codevs1040:统计单词个数

    题目描述 Description

    给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)(管理员注:这里的不能再用指的是位置,不是字母本身。比如thisis可以算做包含2个is)。


    单词在给出的一个不超过6个单词的字典中。
    要求输出最大的个数。
    输入描述 Input Description

    第一行为一个正整数(0<n<=5)表示有n组测试数据
    每组的第一行有二个正整数(p,k)
    p表示字串的行数;
    k表示分为k个部分。
    接下来的p行,每行均有20个字符。
    再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
    接下来的s行,每行均有一个单词。

    输出描述 Output Description

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

     

    样例输入 Sample Input

    1
    1 3
    thisisabookyouareaoh
    4
    is
    a
    ok
    sab

    样例输出 Sample Output

    7

    数据范围及提示 Data Size & Hint

    this/isabookyoua/reaoh

    题解

    AC自动机+划分dp。。。有点长,不过思路挺明确。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<string>
      5 #define maxn 150
      6 using namespace std;
      7 int tot,trie[maxn][30],fail[maxn],flg[maxn],q[maxn],wl[maxn];
      8 char str[30];
      9 string z;
     10 int n,k,m;
     11 int vis[205];
     12 int f[205][45],a[205][205];
     13 void insert(char *s)
     14 {
     15     int cnt(0);
     16     int len = strlen(s);
     17     int p = 0;
     18     for(int i = 0 ; i < len; i ++)
     19     {
     20         int id = s[i] -'a';
     21         if(!trie[p][id]) p = trie[p][id] = ++tot;
     22         else p = trie[p][id];
     23         ++cnt;
     24     }
     25     flg[p] = 1;
     26     wl[p]=cnt;
     27 }
     28 
     29 void getfail()
     30 {
     31     int p = 0,Head = 0,Tail = 0;
     32     q[++Tail] = p;
     33     while(Head != Tail)
     34     {
     35         p = q[++Head];
     36         for(int i = 0 ; i < 26; i ++)
     37         {
     38             int x = trie[p][i];
     39             if(x)
     40             {
     41                 fail[x] = p ? trie[fail[p]][i] :0;
     42                 q[++Tail] = x;
     43             }
     44             else trie[p][i] = trie[fail[p]][i];      
     45         }
     46     }
     47 }
     48 
     49 int match(int len)
     50 {
     51     int cnt(0);
     52     int p = 0;
     53     for(int i = 0 ; i <= len ; i ++)
     54     {
     55         int id = z[i] - 'a';
     56         p = trie[p][id];
     57         int t = p;
     58         while(t)
     59         {
     60             if(flg[t]&&!vis[i-wl[t]+1])
     61             {
     62                 cnt++;
     63                 vis[i-wl[t]+1]=1;
     64             } 
     65             t = fail[t];
     66         }    
     67     }
     68     return cnt;
     69 }
     70 void init()
     71 {
     72     scanf("%d%d",&n,&k);
     73     --k;
     74     for(int i=1 ; i<=n ; ++i)
     75         {
     76             scanf("%s",str);
     77             z+=str;
     78         }
     79     n=20*n-1;
     80     scanf("%d",&m);
     81     for(int i=1; i<=m ;++i)
     82     {
     83         scanf("%s",str);
     84         insert(str);
     85     }
     86     getfail();
     87     for(int i=0 ;i<=n ; ++i)
     88     {
     89         for(int j=0;j<=i;++j)vis[j]=0;
     90         f[i][0]=match(i);
     91         a[0][i]=f[i][0];
     92         if(a[0][i])
     93             for(int j=1; j<=i ; ++j)
     94             {
     95                 a[j][i]=a[j-1][i]-vis[j-1];
     96                 if(!a[j][i])break;
     97             }        
     98     }
     99 }
    100 void dp()
    101 {
    102     for(int p=1;p<=k;++p)
    103         for(int i=p;i<=n;++i)
    104             for(int j=p-1;j<i;++j)
    105                 f[i][p]=max(f[i][p],f[j][p-1]+a[j+1][i]);
    106     printf("%d
    ",f[n][k]);        
    107 }
    108 void sta()
    109 {
    110     for(int i=0 ; i<=n ;++i)
    111     {
    112         for(int j=0 ; j<45 ; ++j)
    113             f[i][j]=0;
    114         for(int j=0 ; j<=n ; ++j)
    115             a[i][j]=0;
    116     }
    117     for(int i=0; i<150 ; ++i)
    118     {
    119         fail[i]=flg[i]=wl[i]=q[i]=0;
    120         for(int j=0;j<30;++j)
    121             trie[i][j]=0;
    122     }
    123     tot=0;
    124     z="";
    125 }
    126 int main(){
    127     int T;
    128     scanf("%d",&T);
    129     while(T--)
    130     {
    131         init();
    132         dp();
    133         sta();
    134     }
    135     return 0;
    136 }
  • 相关阅读:
    HDU 1261 字串数(排列组合)
    Codeforces 488C Fight the Monster
    HDU 1237 简单计算器
    POJ 2240 Arbitrage
    POJ 3660 Cow Contest
    POJ 1052 MPI Maelstrom
    POJ 3259 Wormholes
    POJ 3268 Silver Cow Party
    Codesforces 485D Maximum Value
    POJ 2253 Frogger(最短路)
  • 原文地址:https://www.cnblogs.com/fujudge/p/7545963.html
Copyright © 2011-2022 走看看