• UVALive 3942 Remember The Word (Tire)


    状态是DAG,因此方案用dp统计,dp[i] = sum(dp[i+len(x)]),x是以i开头的前缀且是单词,关键在于快速判断一个前缀是不是单词,可用Trie。

    每一次转移的复杂度是O(maxlen),maxlen是单词的最长长度。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 4005*100//4000*98+26*26+26+1
    ,sigma_size = 26;
    
    
    int ch[maxn][sigma_size];
    bool vis[maxn];
    int nd_cnt;
    
    const int LEN = 3e5+5, mod = 20071027;
    char str[LEN];
    int d[LEN];
    
    void init()
    {
        nd_cnt = 1; memset(ch[0],0,sizeof(ch[0]));
    }
    
    void add(char *s)
    {
        int u = 0;
        int n = strlen(s);
        for(int i = 0; i < n; i++){
            int c = word[i]-'a';
            if(!ch[u][c]){
                memset(ch[nd_cnt],0,sizeof(ch[nd_cnt]));
                vis[nd_cnt] = false;
                ch[u][c] = nd_cnt++;
            }
            u = ch[u][c];
        }
        vis[u] = true;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        char word[120];
        int kas = 0;
        while(gets(str)){
            init();
            int S; scanf("%d
    ",&S);
            while(S--){
                gets(word);
                add(word);
            }
            int n = strlen(str);
            d[n] = 1;
            for(int cur = n-1; cur >= 0; cur--){
                int u = 0; d[cur] = 0;
                for(int i = cur; i < n; i++){
                    int c = str[i]-'a';
                    if(!ch[u][c]) break;
                    u = ch[u][c];
                    if(vis[u]) d[cur] += d[i+1];
                }
                d[cur] %= mod;
            }
            printf("Case %d: %d
    ",++kas,d[0]);
        }
        return 0;
    }
  • 相关阅读:
    poj 2955 Brackets
    HDU 3790 最短路径问题
    畅通工程续
    HDU 1896 六度分离
    HDU
    第九周作业
    第八周作业
    2019年春季学习第七周学习总结
    2019春季学习总结第六周作业
    第五周作业
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4793580.html
Copyright © 2020-2023  润新知