Uva--10029(动规,map,记忆化搜索)

2014-08-04 22:52:19

Problem C: Edit Step Ladders

An edit step is a transformation from one word x to another word y such that x and y are words in the dictionary, and x can be transformed to y by adding, deleting, or changing one letter. So the transformation from dig to dog or from dog to do are both edit steps. An edit step ladder is a lexicographically ordered sequence of words w1, w2, ... wn such that the transformation from wi to wi+1 is an edit step for all i from 1 to n-1.

For a given dictionary, you are to compute the length of the longest edit step ladder.

Input

The input to your program consists of the dictionary - a set of lower case words in lexicographic order - one per line. No word exceeds 16 letters and there are no more than 25000 words in the dictionary.

Output

The output consists of a single integer, the number of words in the longest edit step ladder.

Sample Input

cat
dig
dog
fig
fin
fine
fog
log
wine

Sample Output

5

借鉴:http://blog.csdn.net/wiking__acm/article/details/24382243
思路:字符版LIS,25000个字符,如果用朴素O(n^2)算法会超时(如果Uva数据正常的话),固考虑用dp记忆化搜索,也就是DAG上求最长路的问题了,关键在于图的连边上怎么处理呢。
这里借鉴了别人博客,有add,delete,change三种转换方式,其中add和delete是等价的(串A增一个字符得到串B,那么串B删一个字符必能得到串A)。这里用‘?’字符来插入串中某个位置(‘?’表示可为任意字母),或代替串中某个字符来达到add和change的效果,再把转换后的串进行匹配。这样就可以建图了,记忆化搜索即可。
 1 /*************************************************************************
 2     > File Name: j.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Mon 04 Aug 2014 02:42:06 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <map>
13 #include <string>
14 #include <vector>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 const int maxn = 25000;
19 
20 map<string,int> m;
21 vector<int> g[maxn + 5];
22 string s[maxn + 5];
23 int cnt;
24 
25 string Chan(const string &st,int pos,int len){
26     string tem;
27     for(int i = 0; i < len; ++i){
28         if(i == pos) tem.push_back('?');
29         else tem.push_back(st[i]);
30     }
31     return tem;
32 }
33 
34 string Add(const string &st,int pos,int len){
35     string tem;
36     for(int i = 0; i < len; ++i){
37         if(i == pos) tem.push_back('?');
38         tem.push_back(st[i]);
39     }
40     if(pos == len)
41         tem.push_back('?');
42     return tem;
43 }
44 
45 int dp[maxn + 5];
46 
47 int Solve(int p,int num){
48     if(dp[p] != -1)
49         return dp[p];
50     int tmax = 0;
51     for(int i = 0; i < g[p].size(); ++i){
52         tmax = max(tmax,Solve(g[p][i],num + 1));
53     }
54     return dp[p] = 1 + tmax; //记忆化搜索核心,tmax是后继子情况最优解
55 }
56 
57 int main(){
58     cnt = 0;
59     while(cin >> s[cnt])
60         ++cnt;
61     for(int i = cnt - 1; i >= 0; --i){
62         int l = s[i].size();
63         for(int p = 0; p < l; ++p){
64             string tChan = Chan(s[i],p,l);
65             if(m.count(tChan) > 0)
66                 g[m[tChan]].push_back(i);
67             m[tChan] = i;
68         }
69         for(int p = 0; p <= l; ++p){
70             string tAdd = Add(s[i],p,l);
71             if(m.count(tAdd) > 0)
72                 g[m[tAdd]].push_back(i);
73             m[tAdd] = i;
74         }
75     }
76     memset(dp,-1,sizeof(dp));
77     int ansmax = 0;
78     for(int i = cnt - 1; i >= 0; --i)
79         ansmax = max(ansmax,Solve(i,1));
80     printf("%d\n",ansmax);
81     return 0;
82 }

 



 
posted @ 2014-08-04 23:08  Naturain  阅读(144)  评论(0编辑  收藏  举报