pku1934 LCS+二次DP构造解 注意位压缩只能对应无符号数

题意很简单,找出2个字符串的最长公共字串,并输出所有解。
前一个问题很简单,后面一个问题有点小麻烦
首先,需要在状态转移时记录下所有的最优决策,我是用一个vector来记录的
可以发现,解的结构是一个阶段图,这样就可以用DP来构造解,当然状态是一个集合。
DP其实很灵活,状态不仅仅可以是一个数字、一个字符串,也可以是对象等。像这道题状态转移过程就是集合的合并,应该用左偏树或者spaly的,我偷懒,直接用set了- -结果跑了800MS,汗。。

 1# include <iostream>
 2# include <vector>
 3# include <cstring>
 4# include <set>
 5# include <string>
 6using namespace std;
 7int dp[100][100];
 8vector<int> path[100][100];
 9char str1[100],str2[100];
10set<string> ans[100][100];
11# define encode(a,b) (((a)<<7)|(b))
12int solve(int p1,int p2)
13{
14    if(p1<=0||p2<=0return 0;
15    else if(dp[p1][p2]!=-1return dp[p1][p2];
16    else
17    {
18        if(str1[p1]==str2[p2])
19        {
20           dp[p1][p2]=solve(p1-1,p2-1)+1;
21           path[p1][p2].push_back(encode(p1-1,p2-1));
22        }

23        else
24        {
25            if(solve(p1-1,p2)==solve(p1,p2-1))
26            {
27               dp[p1][p2]=solve(p1-1,p2);
28               path[p1][p2].push_back(encode(p1-1,p2));
29               path[p1][p2].push_back(encode(p1,p2-1));
30            }

31            else if(solve(p1-1,p2)>solve(p1,p2-1))
32            {
33               dp[p1][p2]=solve(p1-1,p2);
34               path[p1][p2].push_back(encode(p1-1,p2));
35            }

36            else
37            {
38                dp[p1][p2]=solve(p1,p2-1);
39                path[p1][p2].push_back(encode(p1,p2-1));
40            }

41        }

42        return dp[p1][p2];
43    }

44}

45void makeans(int p1,int p2,int len)
46{
47     if(len==0)  ans[p1][p2].insert(string(""));
48     else if(ans[p1][p2].size()!=0return;
49     else
50     {
51        for(int i=0;i<path[p1][p2].size();i++)
52        {
53           int t1=path[p1][p2][i]>>7,t2=path[p1][p2][i]&127;
54           if(t1==p1-1&&t2==p2-1)
55           {
56              makeans(p1-1,p2-1,len-1);
57              for(set<string>::iterator it=ans[p1-1][p2-1].begin();it!=ans[p1-1][p2-1].end();it++)
58                ans[p1][p2].insert(*it+str1[p1]);
59           }

60           else if(t1==p1-1)
61           {
62              makeans(p1-1,p2,len);
63              ans[p1][p2].insert(ans[p1-1][p2].begin(),ans[p1-1][p2].end());
64           }

65           else 
66           {
67              makeans(p1,p2-1,len);
68              ans[p1][p2].insert(ans[p1][p2-1].begin(),ans[p1][p2-1].end());
69           }

70        }

71     }

72}

73int main()
74{
75    memset(dp,-1,sizeof(dp));
76    cin>>str1+1>>str2+1;  
77    makeans(strlen(str1+1),strlen(str2+1),solve(strlen(str1+1),strlen(str2+1)));
78    for(set<string>::iterator it=ans[strlen(str1+1)][strlen(str2+1)].begin();it!=ans[strlen(str1+1)][strlen(str2+1)].end();it++)
79       cout<<*it<<endl;
80    //system("pause");
81    return 0;
82}

83

posted on 2010-10-29 14:13 yzhw 阅读(123) 评论(0)  编辑 收藏 引用 所属分类: DP


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年10月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜