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 }