【动态规划】【二分】【最长上升子序列】Vijos P1028 魔族密码

题目链接:

  https://vijos.org/p/1028

题目大意:

  给N个字符串(N<=2000),求能组成词链的单词最多有几个。

  如果在一个由一个词或多个词组成的表中,除了最后一个以外,每个单词都被其后的一个单词所包含

  即前一个单词是后一个单词的前缀,则称词表为一个词链。例如下面单词组成了一个词链:
  i
  int
  integer
  但下面的单词不组成词链:
  integer
  intern

题目思路:

  【动态规划】【二分】【最长上升子序列】

  二分查找最长可达的长度。

 

 1 //
 2 //by coolxxx
 3 ////<bits/stdc++.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<string>
 7 #include<iomanip>
 8 #include<map>
 9 #include<memory.h>
10 #include<time.h>
11 #include<stdio.h>
12 #include<stdlib.h>
13 #include<string.h>
14 //#include<stdbool.h>
15 #include<math.h>
16 #define min(a,b) ((a)<(b)?(a):(b))
17 #define max(a,b) ((a)>(b)?(a):(b))
18 #define abs(a) ((a)>0?(a):(-(a)))
19 #define lowbit(a) (a&(-a))
20 #define sqr(a) ((a)*(a))
21 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
22 #define mem(a,b) memset(a,b,sizeof(a))
23 #define eps (1e-8)
24 #define J 10
25 #define MAX 0x7f7f7f7f
26 #define PI 3.14159265358979323
27 #define N 2004
28 #define M 76
29 using namespace std;
30 typedef long long LL;
31 int cas,cass;
32 int n,m,lll,ans;
33 int q[N];
34 string s[N];
35 void work()
36 {
37     int i,l,r,mid;
38     lll=0;
39     for(i=1;i<=n;i++)
40     {
41         for(l=0,r=lll;l<r;)
42         {
43             mid=(l+r+1)>>1;
44             if(s[i].find(s[q[mid]])==0)l=mid;
45             else r=mid-1;
46         }
47         q[r+1]=i;
48         lll=max(lll,r+1);
49     }
50 }
51 int main()
52 {
53     #ifndef ONLINE_JUDGE
54 //    freopen("1.txt","r",stdin);
55 //    freopen("2.txt","w",stdout);
56     #endif
57     int i,j;
58 //    for(scanf("%d",&cas);cas;cas--)
59 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
60 //    while(~scanf("%s",s))
61     while(~scanf("%d",&n))
62     {
63         for(i=1;i<=n;i++)
64         {
65             cin>>s[i];
66         }
67         work();
68         printf("%d\n",lll);
69     }
70     return 0;
71 }
72 /*
73 //
74 
75 //
76 */
View Code

 

posted @ 2016-08-15 23:38  Cool639zhu  阅读(254)  评论(0编辑  收藏  举报