题解 P1026 【统计单词个数】

· · 题解

这里用的字符串哈希是把str当作一个base进制数处理,因为字母有26个(废话),所以这里选用29这个稍大一些的质数作为基数,顺便取个膜100003(而不是100007100009什么的)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int mod=100003;
int n,m,p,K,f[210][210],s[210][210];;
bool vis[mod],v[210];
char a[210],d[10][210];

int hash(char \*str) {
    int k=0,ln=strlen(str+1);
    for(int i=1; i<=ln; i++) {
        k=k\*29+str[i];
        if(k>=mod) k%=mod;
    }
    return  k;
}

int main() {
    scanf("%d%d",&p,&K);
    for(int i=1,c=1; i<=p; i++) {
        scanf("%s",&a[c]);
        c+=20;
    }
    n=p\*20;
    scanf("%d",&m);
    for(int i=1,h; i<=m; i++) {
        scanf("%s",&d[i][1]);
        h=hash(d[i]);
        if(vis[h]) i--,m--;
        else vis[h]=1;
    }
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            memset(v,0,sizeof v);
            for(int k=1; k<=m; k++) {
                int ln=strlen(d[k]+1);
                for(int l=i; l+ln-1<=j; l++) {
                    if(v[l]) continue;
                    bool flag=0;
                    for(int r=1; r<=ln; r++) {
                        if(a[l+r-1]!=d[k][r]) {
                            flag=1;
                            break;
                        }
                    }
                    if(!flag) s[i][j]++,v[l]=1;
                }
            }
        }
    }
    for(int k=1; k<=K; k++) {
        for(int i=1; i<=n; i++) {
            for(int j=k-1; j<=i-1; j++) {
                f[i][k]=max(f[i][k],f[j][k-1]+s[j+1][i]);
            }
        }
    }
    printf("%d\n",f[n][K]);
    return 0;
}