• luogu_P1026 统计单词个数


    先区间DP处理区间单词个数,在线性DP一次求出答案,注意词典里可能有重复单词

    #include<iostream>
    #include<cstdio>
    
    #define ri register int
    #define u unsigned long long
    
    namespace opt {
    
        inline u in() {
            u x(0),f(1);
            char s(getchar());
            while(s<'0'||s>'9') {
                if(s=='-') f=-1;
                s=getchar();
            }
            while(s>='0'&&s<='9') {
                x=(x<<1)+(x<<3)+s-'0';
                s=getchar();
            }
            return x*f;
        }
    
    }
    
    using opt::in;
    
    #define NN 205
    
    #include<cstring>
    #include<algorithm>
    
    namespace mainstay {
        
        u N,K,M,pow[NN]={(u)1},sum[NN];
        
        char s[NN];
        
        int f[NN][NN],g[NN][NN];
        
        const u bas=131;
        
        struct node{
            u len,hash;
        }a[NN];
        
        inline bool cmp(const node &x,const node &y){
            return x.hash<y.hash;
        }
        
        inline void solve() {
            N=in()*20,K=in();
            for(ri i(1);i<=N;++i) pow[i]=pow[i-1]*bas;
            for(ri i(1);i<=N;++i){
                char _s(getchar());
                while(_s<'a'||_s>'z') _s=getchar();
                sum[i]=sum[i-1]*bas+_s-'a'+1;
            }
            M=in();
            for(ri i(1);i<=M;++i){
                scanf("%s",s+1);
                a[i].len=std::strlen(s+1);
                for(ri j(1);j<=a[i].len;++j) a[i].hash=a[i].hash*bas+s[j]-'a'+1;
            }
            std::sort(a+1,a+M+1,cmp);
            for(ri len(1);len<=N;++len){
                for(ri i(1),j(i+len-1);j<=N;++i,++j){
                    g[i][j]=g[i+1][j];
                    u pre(0);
                    for(ri k(1);k<=M;++k){
                        if(pre==a[k].hash) continue;
                        if(a[k].len<=len&&a[k].hash==sum[i+a[k].len-1]-pow[a[k].len]*sum[i-1]) ++g[i][j];
                        pre=a[k].hash;
                    }
                }
            }
            std::memset(f,-0x3f,sizeof(f));
            f[0][0]=0;
            for(ri i(1);i<=N;++i){
                for(ri j(1);j<=K;++j){
                    for(ri k(0);k<=i-1;++k){
                        f[i][j]=std::max(f[i][j],f[k][j-1]+g[k+1][i]);
                    }
                }
            }
            std::cout<<f[N][K];
        }
    
    }
    
    int main() {
    
        //freopen("x.txt","r",stdin);
        mainstay::solve();
    
    }
  • 相关阅读:
    异常处理 UDP通信
    网络编程 socket套接字 半连接池 通信循环 粘包问题 struct模块 Mac报错
    网络编程 osi七层协议 Time模块补充知识 TCP协议 三次握手 四次挥手
    面向对象 组合 继承
    流式布局
    小程序的瀑布流式布局
    微信小程序的短信接口
    如何高效的编程!
    爱心动画
    em、rpx和px的换算
  • 原文地址:https://www.cnblogs.com/ling-zhi/p/11853098.html
Copyright © 2020-2023  润新知