USACO2.3.1 The Longest Prefix 题解

【算法】动态规划  【难度】★★☆☆☆


这道题花费了很长时间(话说好像没有那道题时间短的)其实很显然是DP,状态转移方程也很容易想到(我是参考了最长公共子序列的思想)。设f[i]表示第i个是否在前缀中,则:

{dp[i]=max{dp[j]+j-i}|i到j-1的字串是primitive。 i<j<=n}

如果没有i-j<=10最坏情况下就会超时!我在这纠结了半天,参照别人的题解才想到的。
还有一点是关于元素的判断。最初是用strcmp但是也会超时。想到了hash,搜了一下有题解说可以把每个元素变成10位2进制数,但是我没找到到底怎么做(= =)。。。所以还是说一下我的方法,也是hash:因为英文字母只有26个,所以2进制下最多5位,最长10个字母也就是50位,还是可以存下的。因为最多只有200个元素,用的时候搜一下就可以了。

【收获】状态转移方程的边界条件很重要

View Code
 1 /*
2 ID: wsc5001
3 LANG: C
4 TASK: prefix
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 char list[203][12];
10 int lenlist[12][203];
11 long long hash[202];
12 char s[200002];
13 int cs;
14 int ct;
15 int f[200010];
16 int pd(int b,int e)
17 {
18 int i,j,k;
19 long long bf=0;
20 for (i=b;i<=e;i++)
21 {
22 if (s[i]>='A'&&s[i]<='Z') bf+=s[i]-'A'+1;
23 bf=(bf<<5);
24 }
25 for (i=0;i<10+1-e+b-1;i++)
26 bf=(bf<<5);
27 for (i=0;i<ct;i++)
28 if (hash[i]==bf)
29 return 1;
30 return 0;
31 }
32 long long hashit(int coin)
33 {
34 int i,j,k;
35 long long ans=0;
36 for (i=0;i<10+1;i++)
37 {
38 if (list[coin][i]>='A'&&list[coin][i]<='Z') ans+=list[coin][i]-'A'+1;
39 ans=(ans<<5);
40 }
41 return ans;
42 }
43 int main()
44 {
45 freopen("prefix.in","r",stdin);
46 freopen("prefix.out","w",stdout);
47 int i,j,k,flag,e;
48 char gabbage;
49 for (i=0;i<12;i++)
50 lenlist[i][0]=1;
51 i=0;
52 scanf("%s",&list[i]);
53 while (list[i][0]!='.')
54 {
55 hash[i]=hashit(i);
56 i++;
57 scanf("%s",&list[i]);
58 }
59 ct=i;
60 i=0;flag=0;
61 scanf("%c",&gabbage);
62 while (1)
63 {
64 scanf("%c",&gabbage);
65 if (gabbage>='A'&&gabbage<='Z')
66 {s[i]=gabbage;i++;flag=0;}
67 else
68 flag+=1;
69 if (flag==2)
70 break;
71 }
72 cs=i;
73 f[0]=1;
74 for (i=1;i<=cs;i++)
75 {
76 for (j=i-1;j>=0;j--)
77 {
78 if (i-j+1>12||f[i]==1) break;//important!!!!!!
79 e=pd(j,i-1);
80 if (e==1&&f[j]==1)
81 {f[i]=1;}
82 }
83 }
84 //printf("%d\n",cs);
85 //for (i=1;i<=cs;i++) printf("%d ",f[i]); printf("\n");
86 flag=0;
87 for (i=cs;i>=1;i--)
88 if (f[i]==1)
89 {printf("%d\n",i);flag=1;break;}
90 if (flag==0) printf("0\n");
91 //system("pause");
92 fclose(stdin);
93 fclose(stdout);
94 }



posted @ 2012-03-25 19:38  wsc500  阅读(329)  评论(0编辑  收藏  举报