【Trie+DP】BZOJ1212-[HNOI2004]L语言
【题目大意】
给出字典和文章,求出文章能够被理解的最长前缀。
【思路】
1A……!先用文章建立一棵Trie树,然后对于文章进行DP。f[i]表示文章中长度为i的前缀能否被理解,如果f[i]能理解,顺着下一个字母开始暴力走一遍字典树,递推下去。最后输出最大的满足f[i]=1的i即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdlib> 6 using namespace std; 7 const int MAXN=(1<<20)+10; 8 const int maxlen=10; 9 struct Trie 10 { 11 Trie* next[26]; 12 int avail; 13 int dep; 14 Trie() 15 { 16 for (int i=0;i<26;i++) next[i]=NULL; 17 avail=0; 18 dep=0; 19 } 20 }; 21 int n,m,f; 22 Trie* rt; 23 24 void insert(Trie* rt,char* str) 25 { 26 int len=strlen(str); 27 Trie* now=rt; 28 for (int i=0;i<len;i++) 29 { 30 int index=str[i]-'a'; 31 if (now->next[index]==NULL) 32 { 33 now->next[index]=new Trie; 34 now->next[index]->dep=now->dep+1; 35 } 36 now=now->next[index]; 37 } 38 now->avail=1; 39 } 40 41 int dp(Trie* rt,char* str) 42 { 43 int f[MAXN]; 44 int len=strlen(str),ans; 45 memset(f,0,sizeof(f)); 46 for (int i=0;i<=len;i++) 47 { 48 if (f[i] || i==0) 49 { 50 ans=i; 51 Trie* now=rt; 52 for (int j=i;j<=i+maxlen-1;j++) 53 { 54 if (str[j]>'z' || str[j]<'a') break; 55 int index=str[j]-'a'; 56 if (now->next[index]==NULL) break; 57 now=now->next[index]; 58 if (now->avail) f[i+now->dep]=1; 59 } 60 } 61 } 62 return ans; 63 } 64 65 void init() 66 { 67 rt=new Trie; 68 scanf("%d%d",&n,&m); 69 for (int i=0;i<n;i++) 70 { 71 char str[11]; 72 scanf("%s",str); 73 insert(rt,str); 74 } 75 } 76 77 void get_ans() 78 { 79 for (int i=0;i<m;i++) 80 { 81 char str[MAXN]; 82 scanf("%s",str); 83 cout<<dp(rt,str)<<endl; 84 } 85 } 86 87 int main() 88 { 89 init(); 90 get_ans(); 91 return 0; 92 }