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 }
做法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 }