1. 程式人生 > >(trie)UVALive - 3942 Remember the Word

(trie)UVALive - 3942 Remember the Word

span map remember efi problem 註意 find 不存在 中間節點

題目鏈接

設d[i]表示從下標i的字符開始的字符串的分解方法數,顯然有倒序的遞推公式。

需要求每個位置開始是否能組成模式串的前綴,才可以建立正確的遞推。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9
#include <map> 10 #include <list> 11 #include <vector> 12 #include <stack> 13 #define mp make_pair 14 #define MIN(a,b) (a>b?b:a) 15 #define rank rankk 16 //#define MAX(a,b) (a>b?a:b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int MAX=3e5+5
; 20 const int INF=1e9+5; 21 const int B=1024;//桶的大小 22 const double M=4e18; 23 const int MAX_NODE=MAX; 24 const int sigma_size=30; 25 using namespace std; 26 //const int MOD=1e9+7; 27 const int MOD=20071027; 28 typedef pair<int,int> pii; 29 const double eps=0.000000001; 30 31 struct Trie 32 { 33 int
ch[MAX_NODE][sigma_size];//點數、“字母”數 34 int val[MAX_NODE]; 35 int num;//結點總數 36 Trie(){num=1;memset(ch[0],0,sizeof(ch[0]));}//初始時僅有根節點 37 void clear() { num = 1; memset(ch[0], 0, sizeof(ch[0])); } 38 int idx(char c)//返回對應字符的編號 39 { 40 return c-a; 41 } 42 /* 43 插入字符串s,附加信息為v。註意v必須非0,因為0代表:本結點不是單詞結點 44 */ 45 void insert(const char *s,int v) 46 { 47 int u=0,len=strlen(s); 48 for(int i=0;i<len;i++) 49 { 50 int c=idx(s[i]); 51 if(!ch[u][c])//結點不存在 52 { 53 memset(ch[num],0,sizeof(ch[num])); 54 val[num]=0;//中間節點的附加信息為0 55 ch[u][c]=num++;//新建結點 56 } 57 u=ch[u][c];//往下走 58 } 59 val[u]=v;//字符串的最後一個字符的附加信息為v 60 } 61 /* 62 查詢字符串的“附加信息” 63 查詢過程中間中斷返回0 64 */ 65 int check(char *s) 66 { 67 int u=0,len=strlen(s); 68 for(int i=0;i<len;i++) 69 { 70 int c=idx(s[i]); 71 if(!ch[u][c]) 72 return 0; 73 u=ch[u][c]; 74 } 75 return val[u]; 76 } 77 /* 78 找字符串s的長度不超過len的前綴 79 */ 80 void find_prefixes(const char *s,int len,vector <int> &ans) 81 { 82 int u=0; 83 for(int i=0;i<len;i++) 84 { 85 if(s[i]==\0) 86 break; 87 int c=idx(s[i]); 88 if(!ch[u][c]) 89 break; 90 u=ch[u][c]; 91 if(val[u]!=0)//過程中所有找到的全都push進去 92 ans.push_back(val[u]); 93 } 94 } 95 }; 96 char a[MAX]; 97 int s,d[MAX],len,siz[MAX],cnt; 98 Trie dic; 99 char tem[MAX]; 100 vector <int> an; 101 int main() 102 { 103 while(~scanf("%s",a)) 104 { 105 dic.clear(); 106 an.clear(); 107 scanf("%d",&s); 108 for(int i=1;i<=s;i++) 109 { 110 scanf("%s",tem); 111 siz[i]=strlen(tem); 112 dic.insert(tem,i); 113 } 114 memset(d,0,sizeof(d)); 115 len=strlen(a); 116 d[len]=1; 117 for(int i=len-1;i>=0;i--) 118 { 119 an.clear(); 120 dic.find_prefixes(a+i,len-i,an); 121 for(int j=0;j<an.size();j++) 122 { 123 d[i]=(d[i]+d[i+siz[an[j]]])%MOD; 124 } 125 } 126 printf("Case %d: %d\n",++cnt,d[0]); 127 } 128 }

(trie)UVALive - 3942 Remember the Word