UVALive

  递推:$d(i) $表示从第$i$个字符开始到末尾的字符串(即后缀S[i...n])的分解方案数,则$d(i) = sum {d(i + len(x))} $,其中字符串$x$代表S[i...n]的前缀,且x可以和某个单词匹配。判断后缀串S[i...n]能和哪些单词匹配,使用字典树来实现O(100)复杂度判断。

 

AC代码

#include <stdio.h>
#include <string.h>
const int MOD = 20071027;
const int maxnode = 4000 * 100 + 5;
const int sigma_size = 26;
const int maxn = 300000 + 5;

char S[maxn], sb[100 + 5];
int d[maxn];

struct Trie {
    int ch[maxnode][sigma_size];
    int val[maxnode];
    int sz;
    void clear() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    int idx(char c) {
        return c - 'a';
    }

    void insert(char *s) {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++) {
            int c = idx(s[i]);
            if(!ch[u][c]) {
                val[sz] = 0;
                memset(ch[sz], 0, sizeof(ch[sz]));
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = n;
    }

    void query_prefix(char *s, int i, int *d) {
        int u = 0;
        for(int j = 0; s[j] != ''; j++) {
            int c = idx(s[j]);
            if(!ch[u][c]) break;
            u = ch[u][c];
            if(val[u]) {
                d[i] = (d[i] + d[i + val[u]]) % MOD;
            }
        }
    }
};

Trie tree;

int main() {
    int m, kase = 1;
    while(scanf("%s", S) == 1) {
        tree.clear();
        scanf("%d", &m);
        for(int i = 0; i < m; i++) {
            scanf("%s", sb);
            tree.insert(sb);
        }
        int n = strlen(S);
        d[n] = 1;
        for(int i = n-1; i >= 0; i--) {
            d[i] = 0;
            tree.query_prefix(S+i, i, d);
        }   
        printf("Case %d: %d
", kase++, d[0]);
    }
    return 0;
}

如有不当之处欢迎指出!

原文地址:https://www.cnblogs.com/flyawayl/p/8873117.html