1401 - Remember the Word

注意到单词的长度最长100,其实最糟糕复杂度应该能到O(300005*100),需要注意的是在字典树上匹配单词时,一旦不匹配,则后面的就不会匹配,需要break出来(这个害我TLE查了半天,日!),还有,要注意strlen的时候,那个api的复杂度貌似是O(n)的,题目中提到输入数据的不同的test case之间有一个blank line,我理解成输出不同case之间要回车,OJ居然没判成PE,而是判成WA,这两天题写的真蛋疼(吐槽下)。

#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <iostream>
using namespace std;

const int MAXN =  300005;
const int M = 20071027;

typedef long long int64;

char ch[MAXN];
int64 dp[MAXN];

int id[4005 * 105][26], cnt;
bool flag[4005 * 105];


class DicNode {
public:
    bool flag;
    DicNode *sons[26];
    DicNode() {
        flag = false;
        memset(sons, NULL, sizeof(sons));
    }
};

class DicTree2 {
public:
    DicTree2() {
        cnt = 1;
        memset(id, -1, sizeof(id));
        memset(flag, false, sizeof(flag));
    }
    ~DicTree2() {
    
    }
    void insert(const char *s) {
        int len = strlen(s);
        int node = 0;
        for (int i = 0; i < len; i++) {
            if (id[node][s[i] - 'a'] == -1) {
                id[node][s[i] - 'a'] = cnt++;
            } 
            node = id[node][s[i] - 'a'];
            if (i == len - 1) {
                flag[node] = true;
            }
        }
    }
    bool query(const char *s) {
        int len = strlen(s);
        int node = 0;
        for (int i = 0; i < len; i++) {
            if (id[node][s[i] - 'a'] == -1) {
                return false;
            } 
            node = id[node][s[i] - 'a'];
        }
        return flag[node];
    }
    int64 f(int b, int len) {
        if (dp[b] != -1) return dp[b];
        dp[b] = 0;
        if (b == len) return dp[b] = 1;
        int node = 0;
        for (int i = b; i < len; i++) {
            if (id[node][ch[i] - 'a'] != -1) {
                node = id[node][ch[i] - 'a'];
                if (flag[node]) dp[b] = (dp[b] + f(i + 1, len)) % M;
            } else {
                break;
            }
        }
        return dp[b];
    }
};

class DicTree {
public:
    DicNode *root;
    DicTree() {
        root = new DicNode();
    }
    ~DicTree() {
        if (NULL != root) {
            free(root);
        }
    }
    void free(DicNode *node) {
        for (int i = 0; i < 26; i++) {
            if (node->sons[i] != NULL) {
                free(node->sons[i]);
            }
        }
        delete node;
    }
    void insert(const char *s) {
        int len = strlen(s);
        DicNode *node = root;
        for (int i = 0; i < len; i++) {
            if (node->sons[s[i] - 'a'] == NULL) {
                node->sons[s[i] - 'a'] = new DicNode();
            } 
            node = node->sons[s[i] - 'a'];
            if (i == len - 1) {
                node->flag = true;
            }
        }
    }
    bool query(const char *s) {
        int len = strlen(s);
        DicNode *node = root;
        for (int i = 0; i < len; i++) {
            if (node->sons[s[i] - 'a'] == NULL) {
                return false;
            }
            node = node->sons[s[i] - 'a'];
        }
        return node->flag;
    }
    int64 f(int b, int len) {
        if (dp[b] != -1) return dp[b];
        dp[b] = 0;
        if (b == len) return dp[b] = 1;
        DicNode *node = root;
        for (int i = b; i < len; i++) {
            if (node->sons[ch[i] - 'a'] != NULL) {
                node = node->sons[ch[i] - 'a']; 
                if (node->flag) dp[b] = (dp[b] + f(i + 1, len)) % M; 
            } else {
                break;
            } 
        }
        return dp[b];
    }
};



int main() {
    int c = 0;
    while (scanf("%s", ch) != EOF) {
        int s;
        scanf("%d", &s);
        DicTree dic;
        for (int i = 0; i < s; i++) {
            char str[105];
            scanf("%s", str);
            dic.insert(str);
        }
        memset(dp, -1, sizeof(dp));
        printf("Case %d: %lld\n", ++c, dic.f(0, strlen(ch)));
    }
}

 

 

posted @ 2013-09-05 10:47  litstrong  阅读(225)  评论(0)    收藏  举报