uva1401 - Remember the Word 前缀树DP

来源:互联网 发布:windows更新过程中关闭 编辑:程序博客网 时间:2024/05/30 23:32

Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie.

Since Jiejie can't remember numbers clearly, he just uses sticks to help himself. Allowing for Jiejie's only 20071027 sticks, he can only record the remainders of the numbers divided by total amount of sticks.

The problem is as follows: a word needs to be divided into small pieces in such a way that each piece is from some given set of words. Given a word and the set of words, Jiejie should calculate the number of ways the given word can be divided, using the words in the set.

Input 

The input file contains multiple test cases. For each test case: the first line contains the given word whose length is no more than 300 000.

The second line contains an integer S, 1$ \le$S$ \le$4000.

Each of the following S lines contains one word from the set. Each word will be at most 100 characters long. There will be no two identical words and all letters in the words will be lowercase.

There is a blank line between consecutive test cases.

You should proceed to the end of file.

Output 

For each test case, output the number, as described above, from the task description modulo 20071027.

Sample Input 

abcd 4 a b cd ab

Sample Output 

Case 1: 2

  给一个字符串和一些单词,这个字符串由这些单词组成的情况有多少种。

  若正着推,dp[i]代表前i个字母能由单词组成的情况有多少种,那么dp[i]=sum{dp[i-len],str[i-len+1]...str[i]是一个单词}。如果对于每个i都枚举一遍所有单词会超时,用前缀树找从s[i]开始到结尾的这个路径,中途若遇到单词标记就可以进行一次dp,若位置str[j]被标记,则更新sum[j]=(sum[j]+sum[i-1])%MOD。注意这是用前面的状态更新后面的状态。若倒着推,设dp[i]为后i个字母能由单词组成的情况有多少种,dp倒着进行,则sum[i]=(sum[i]+sum[j+1])%MOD,比较符合一般DP的思路。

  可以在前缀树查找的过程中完成dp,也可以查找的时候把点记下来,查找完后再dp。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 300010#define MAXNODE 400010#define MOD 20071027#define INF 0x3f3f3f3fusing namespace std;int N,sum[MAXN];char str[MAXN];struct Tire{    int ch[MAXNODE][26];    int val[MAXNODE];    int sz;    Tire(){        memset(ch,0,sizeof(ch));        memset(val,0,sizeof(val));        sz=1;    }    int get_id(char c){        return c-'a';    }    void insert(char *s,int v){        int u=0;        for(int i=0;s[i];i++){            int c=get_id(s[i]);            if(!ch[u][c]) ch[u][c]=sz++;            u=ch[u][c];        }        val[u]=1;    }    void query(char *s){        int u=0;        for(int i=1;s[i];i++){            int u=0;            for(int j=i;s[j];j++){                int c=get_id(s[j]);                if(!ch[u][c]) break;                u=ch[u][c];                if(val[u]) sum[j]=(sum[j]+sum[i-1])%MOD;            }        }    }};int main(){    freopen("in.txt","r",stdin);    while(scanf("%s",str+1)!=EOF){        scanf("%d",&N);        Tire tire;        char s[110];        for(int i=1;i<=N;i++){            scanf("%s",s);            tire.insert(s,1);        }        tire.query(str);        printf("%d\n",sum[strlen(str+1)]);    }    return 0;}



0 0
原创粉丝点击