• 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 }



  • 相关阅读:
    方便的使用单击和双击更新DataGrid中的数据的例子 (转)
    针对 .NET 开发人员的存储过程评估(转)
    ASP.NET创建Web服务之XML基础结构(转)
    移动业务咨询系统--用VoiceXML开发语音应用程序(转)
    创建动态数据输入用户界面 (转)
    ASP.NET缓存:方法和最佳实践(转)
    ASP.NET 应用程序性能优化(转)
    出色图形用户界面(GUI)设计规范(转,中英对比)
    五种常见的ASP.NET安全缺陷(转)
    ASP.net控件开发系列之(一)开篇(转)
  • 原文地址:https://www.cnblogs.com/loveidea/p/2416938.html
Copyright © 2020-2023  润新知