【SCU - 3596 Article Decryption】 字典樹 + DP

I - Article Decryption


Time Limit:1000ms Memory Limit:65536KB

Description

You are given an dictionary in which there are N words.
Also, you are given an article with the length of L and
there`s no punctuation.
How many way can you translate this article?

Input

The first line is an integer T which stands for the number of test cases.
Then T test cases follow.
The first line of a test case contains an integer N (1<=N<=1000).
Each of the following N lines contains one word . 
The length of each word is guaranteed to be less than or eaqul to 1000.
The next line contains some characters which describe the article. 
The characters are lowercase letters.

Output

For each case output its answer after mod by 835672545.

Sample Input

2
5
ab
cb
bc
ba
a
abcba
3
a
ba
ab
ababa

Sample Output

2
3

題意:給定n個字符串和一篇文章,問用這些字符串組成這篇文章的方法有多少種。


分析:先將給定的字符串存入字典樹中,在樹中定義一個cnt用來記錄存入的每個字符串以最後一個字母結尾時的數量。這樣我們可以定義一個數組dp[MX]來記錄不同長度下的符合條件的組合方法。

dp[i] += dp[i-1] * query(s[ ])

query(s[ ])表示所查詢的字符串的個數
最終答案就是dp[len] len爲文章的長度

代碼如下:
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define mod 835672545
#define LL long long
#define INF 0x3f3f3f3f

using namespace std;
const int MX = 1e5 + 5;

int tot;
int dp[MX];
char temp[MX];
struct node{
    int nxt[26];
    int cnt;
    void init(){
        cnt = 0;
        memset(nxt, 0, sizeof(nxt));
    }
}tree[MX];

void add(char s[]){
    int now = 0, x;
    for(int i = 0; s[i] != '\0'; i++){
        x = s[i] - 'a';
        if(tree[now].nxt[x] == 0){
            tree[++tot].init();
            tree[now].nxt[x] = tot;
        }
        now = tree[now].nxt[x];
    }
    tree[now].cnt++;
}

int query(char s[]){
    int now = 0, x;
    for(int i = 0; s[i] != '\0'; i++){
        x = s[i] - 'a';
        if(tree[now].nxt[x]){
            now = tree[now].nxt[x];
        }
        else return 0;
    }
    return tree[now].cnt;
}

int main() {
    int t;
    scanf("%d", &t);
    while(t--){
        tot = 0;
        tree[0].init();
        int n;
        scanf("%d", &n);
        char s[1005];
        for(int i = 0; i < n; i++){
            scanf("%s", s);
            add(s);
        }
        scanf("%s", s+1);
        memset(dp, 0, sizeof(dp));
        memset(temp, 0, sizeof(temp));
        int len = strlen(s+1);
        dp[0] = 1;
        for(int i = 1; i <= len; i++){
            temp[i] = s[i];
            for(int j = 1; j <= i; j++){
                if(dp[j-1]){
                    dp[i] += dp[j-1] * query(temp + j);
                }
                if(dp[i] >= mod) dp[i] %= mod;
            }
        }
        printf("%d\n", dp[len]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章