bzoj 1212: [HNOI2004]L语言
思路:字典树+dp, dp[ i ] 表示 前缀到 i 能不能被理解, 如果dp[ i ] 是能被理解的那么, 把i + 1, i + 2 .... 在字典树上走,走到一个单词就转移。
,这样可行的原因是因为模板串长度不超过10,所以字典树的深度不会超过10, 所以进行一次dp的复杂度为 10 * n;
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define ll long long 4 #define fi first 5 #define se second 6 #define mk make_pair 7 #define pii pair<int,int> 8 #define piii pair<int, pair<int,int> > 9 10 using namespace std; 11 12 const int N = 1e6 + 7; 13 const int inf = 0x3f3f3f3f; 14 const LL INF = 0x3f3f3f3f3f3f3f3f; 15 const int mod = 1e9 + 7; 16 const int Mod = 2009; 17 18 int ch[500][26], tot, n, m; 19 bool is[500], dp[N]; 20 char s[N]; 21 int getNode() { 22 ++tot; 23 memset(ch[tot], 0, sizeof(ch[tot])); 24 is[tot] = false; 25 return tot; 26 } 27 28 void add(const char *s, int n) { 29 int u = 0; 30 for(int i = 0; i < n; i++) { 31 if(!ch[u][s[i] - 'a']) { 32 ch[u][s[i] - 'a'] = getNode(); 33 } 34 u = ch[u][s[i] - 'a']; 35 } 36 is[u] = true; 37 } 38 39 40 int main() { 41 scanf("%d%d", &n, &m); 42 for(int i = 1; i <= n; i++) { 43 scanf("%s", s); 44 add(s, strlen(s)); 45 } 46 47 while(m--) { 48 memset(dp, false, sizeof(dp)); 49 scanf("%s", s + 1); 50 n = strlen(s + 1); 51 dp[0] = true; 52 for(int i = 0; i < n; i++) { 53 if(dp[i]) { 54 int j = i + 1, u = 0; 55 while(j <= n && ch[u][s[j] - 'a']) { 56 u = ch[u][s[j] - 'a']; 57 if(is[u]) dp[j] = true; 58 j++; 59 } 60 } 61 } 62 63 int ans = 0; 64 for(int i = 1; i <= n; i++) 65 if(dp[i]) ans = i; 66 printf("%d\n", ans); 67 } 68 return 0; 69 } 70 71 72 /* 73 */