UVALive - 3942 Remember the Word

input

字符串s   1<=len(s)<=300000

n    1<=n<=4000

word1

word2

...

wordn

1<=len(wordi)<=100

output

由一个或多个word拼成s的种数%20071027.

做法1:dp:单词长度最多为100,d[i]表示到第i个字符结束的种数,则如果d[j]到d[i]这段字符能从trie中找到,d[i]+=d[j],i-100<j<=i

  1 //1225ms
  2 #include <cstdio>
  3 #include <queue>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <cstdlib>
  7 #include <algorithm>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <ctime>
 12 #include <cmath>
 13 #include <cctype>
 14 #define MAX 100000
 15 #define LL long long
 16 #define mod 20071027
 17 struct trie
 18 {
 19     int ch[4*MAX][26];
 20     bool val[4*MAX];
 21     int sz;
 22     trie()
 23     {
 24         sz=1;
 25         memset(ch[0],0,sizeof(ch[0]));
 26     }
 27     int idx(char &c) { return c-'a';}
 28     char* insert(char*s)
 29     {
 30         int u=0;
 31         for(;*s;s++)
 32         {
 33             int c=idx(*s);
 34             if(!ch[u][c])
 35             {
 36                 memset(ch[sz],0,sizeof(ch[sz]));
 37                 val[sz]=0;
 38                 ch[u][c]=sz++;
 39             }
 40             u=ch[u][c];
 41         }
 42         val[u]=1;
 43         return s;
 44     }
 45     int find(char*s,int n)
 46     {
 47         int u=0;
 48         for(int i=0;i<n;i++)
 49         {
 50             int c=idx(s[i]);
 51             if(!ch[u][c]) return 0;
 52             u=ch[u][c];
 53         }
 54         return val[u];
 55     }
 56 };
 57 trie t;
 58 char s[3*MAX+10],word[110];
 59 int n,maxl,d[3*MAX+10],cas=1;
 60 int main()
 61 {
 62     //freopen("/home/user/桌面/in","r",stdin);
 63     while(scanf("%s",s)==1)
 64     {
 65         memset(t.ch[0],0,sizeof(t.ch[0]));
 66         t.sz=1;
 67         scanf("%d",&n);
 68         maxl=0;
 69         while(n--)
 70         {
 71             scanf("%s",word);
 72             int l=t.insert(word)-word;
 73             maxl=std::max(maxl,l);
 74         }
 75         n=strlen(s);
 76         memset(d,0,sizeof(d));
 77         int u=0,work=0;
 78         for(int i=0;i<maxl;i++)
 79         {
 80             int c=t.idx(s[i]);
 81             if(!t.ch[u][c]) break;
 82             u=t.ch[u][c];
 83             if(t.val[u])
 84             {
 85                 work=1;
 86                 d[i]=1;
 87             }
 88         }
 89 //        for(int i=0;i<=n;i++) printf("%d ",d[i]);printf("\n");
 90         if(work)
 91         {
 92                for(int i=1;i<n;i++)
 93             {
 94                 for(int j=1;j<=maxl;j++)
 95                 {
 96                     if(i-j>=0&&t.find(s+i-j+1,j)) d[i]=(d[i]+d[i-j])%mod;
 97                 }
 98             }
 99         }
100 //        for(int i=0;i<=n;i++) printf("%d ",d[i]);printf("\n");
101         printf("Case %d: %d\n",cas++,d[n-1]);
102     }
103     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
104     return 0;
105 }
dp

做法2:直接模拟:一开始只有一条路找,每个单词结束时分出一条路从头开始

 1 //79ms
 2 #include <cstdio>
 3 #include <queue>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <cstdlib>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <ctime>
12 #include <cmath>
13 #include <cctype>
14 #define MAX 100000
15 #define LL long long
16 #define mod 20071027
17 struct trie
18 {
19     int ch[4*MAX][26];
20     bool val[4*MAX];
21     int sz;
22     trie()
23     {
24         sz=1;
25         memset(ch[0],0,sizeof(ch[0]));
26     }
27     int idx(char &c) { return c-'a';}
28     void insert(char*s)
29     {
30         int u=0;
31         for(;*s;s++)
32         {
33             int c=idx(*s);
34             if(!ch[u][c])
35             {
36                 memset(ch[sz],0,sizeof(ch[sz]));
37                 val[sz]=0;
38                 ch[u][c]=sz++;
39             }
40             u=ch[u][c];
41         }
42         val[u]=1;
43     }
44 };
45 trie t;
46 char s[3*MAX+10],word[110];
47 int n,cas=1,head[2][110],count[2][110],num[2];
48 int main()
49 {
50     //freopen("/home/user/桌面/in","r",stdin);
51     while(scanf("%s",s)==1)
52     {
53         memset(t.ch[0],0,sizeof(t.ch[0]));
54         t.sz=1;
55         scanf("%d",&n);
56         while(n--)
57         {
58             scanf("%s",word);
59             t.insert(word);
60         }
61         int d=1;
62         num[d]=1;
63         head[d][0]=0;
64         count[d][0]=1;
65         for(char*p=s;*p;p++,d^=1)
66         {
67 //            printf("%d %d\n",count[d][0],d);
68             int &idx=num[d^1]=1;
69             int c=t.idx(*p);
70             head[d^1][0]=0;
71             count[d^1][0]=0;
72             for(int i=0;i<num[d];i++)
73             {
74                 int &f=head[d][i];
75                 if(t.ch[f][c])//继续走到下一个字母
76                 {
77                     if(t.val[t.ch[f][c]])//走完一个单词,从头开始,总是head[d][0]
78                     {
79                         count[d^1][0]+=count[d][i];
80                         count[d^1][0]%=mod;
81                     }
82                     head[d^1][idx]=t.ch[f][c];
83                     count[d^1][idx++]=count[d][i];
84                 }
85             }
86         }
87 //        printf("%d %d\n",count[d][0],d);
88         printf("Case %d: %d\n",cas++,count[d][0]);
89     }
90     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
91     return 0;
92 }
模拟
posted @ 2015-12-03 13:50  cdongyang  阅读(201)  评论(0编辑  收藏  举报