现在的位置: 首页 > 综合 > 正文

LA 3942 Remember the Word (Trie)

2018年01月12日 ⁄ 综合 ⁄ 共 1350字 ⁄ 字号 评论关闭

Remember the Word

题目:链接
题意:给出一个有S个不同单词组成的字典和一个长字符串。把这个字符串分解成若干个单词的连接(单词可以重复使用),有多少种方法?
思路:令d[i]表示从字符i开始的字符串(后缀s[i..L])的分解数,这d[i] = sum{d(i+len(x)) | 单词x是其前缀}。然后将所有单词建成一个Trie树,就可以将搜索单词的复杂度降低。
代码:
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, n) for (int i = 0; i < n; i++)
#define debug puts("===============")
typedef long long ll;
using namespace std;
const int maxnode = 400010, charset = 26;
int d[300100] = {0}, len;
const int mod = 20071027;
struct Trie {
    int ch[maxnode][charset];
    int val[maxnode];
    int sz;
    void init() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    int idx(char c) {
        return c - 'a';
    }
    void insert(char *s, int v) {
        int u = 0, n = strlen(s);
        for (int i = 0; i < n; i++) {
            int c = idx(s[i]);
            if (!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
    }
    void query(char *s, int x) {
        int u = 0, ans = 0;
        for (int i = x; i < len; i++) {
            int c = idx(s[i]);
            if (!ch[u][c]) return ;
            u = ch[u][c];
            if (val[u]) d[x] = (d[x] + d[i + 1]) % mod;
        }
    }
};
char w[110], str[300100];
Trie T;
int main () {
    int cnt = 1, n;
    while(~scanf("%s", str)) {
        len = strlen(str);
        scanf("%d", &n);
        T.init();
        for(int i = 0; i < n; i++) {
            scanf("%s", w);
            T.insert(w, 1);
        }
        d[len] = 1;
        for (int i = len - 1; i >= 0; i--) {
            d[i] = 0;
            T.query(str, i);
        }
        printf("Case %d: %d\n", cnt++, d[0]);
    }
    return 0;
}

抱歉!评论已关闭.