ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

UVA 1625 "Color Length" (基础DP)

2019-06-12 16:52:17  阅读:395  来源: 互联网

标签:fir 字符 1625 Color int Length maxn 个字符 las


传送门

 

•参考资料

  [1]:HopeForBetter

•题意

  

•题解(by 紫书)

  

•我的理解

  用了一上午的时间,参考紫书+上述博文,终于解决了疑惑;

  定义第一个颜色序列用串 s 表示,第二个用串 t 表示,下标均从 1 开始;

  定义dp(i,j)表示串 s 的前 i 个字符与串 t 的前 j 个字符合并的最小值;

  

 

  ' ? ' 是加什么呢?

  分析一下,当前的新序列包含哪些类型的字符:

  1)当前新序列包含字符 ch 的开始和结束;

  2)当前新序列只包含字符 ch 的开始,而不包含其结束;

  3)当前新序列不包含字符 ch;

  就情况①,将 si 插入到尾部后,你会发现,这个新插入的元素只会影响 1) 类型字符,怎么影响呢?

  当前字符 si 的插入会使得 1) 类型的字符首尾距离增加 1;

  那么,情况①中的 ' ? ' 指的就是 s 串的前 i-1 个字符与 t 串中的前 j 个字符的 1) 类型的字符个数;

  情况②同理;

  那么,如何求解 "s 串的前 i-1 个字符与 t 串中的前 j 个字符的 1) 类型的字符个数" 呢?

  定义 w(i,j) 表示串 s 的前 i 个字符与串 t 的前 j 个字符包含的 1) 类型的字符总个数;

 1 struct Data
 2 {
 3     int fir,las;
 4     Data(int fir=INF,int las=0):fir(fir),las(las){}
 5 };
 6 int w[maxn][maxn];
 7 
 8 void Preset()
 9 {
10     /**
11         a[i].fir:字符 'A'+i 在串s中第一次出现的位置
12         a[i].las:字符 'A'+i 在串s中最后一次出现的位置
13         b[i].fir:字符 'A'+i 在串t中第一次出现的位置
14         b[i].las:字符 'A'+i 在串t中最后一次出现的位置
15     */
16     Data a[30],b[30];
17     for(int i=1;i <= n;++i)
18     {
19         Data &tmp=a[s[i]-'A'];
20         tmp.fir=min(tmp.fir,i);
21         tmp.las=i;
22     }
23     for(int i=1;i <= m;++i)
24     {
25         Data &tmp=b[t[i]-'A'];
26         tmp.fir=min(tmp.fir,i);
27         tmp.las=i;
28     }
29     w[0][0]=0;
30     for(int i=0;i <= n;++i)
31     {
32         for(int j=0;j <= m;++j)
33         {
34             if(i)
35             {
36                 w[i][j]=w[i-1][j];
37                 int k=s[i]-'A';
38                 if(a[k].fir == i && b[k].fir > j)///判断si是否为首次出现的
39                     w[i][j]++;
40                 if(a[k].las == i && b[k].las <= j)///判断si是否为结尾字符
41                     w[i][j]--;
42             }
43             if(j)
44             {
45                 w[i][j]=w[i][j-1];
46                 int k=t[j]-'A';
47                 if(b[k].fir == j && a[k].fir > i)///判断tj是否为首次出现的
48                     w[i][j]++;
49                 if(b[k].las == j && a[k].las <= i)///判断tj是否为结尾字符
50                     w[i][j]--;
51             }
52         }
53     }
54 }
求解w(i,j)

  求解完 w(i,j) 后,状态转移方程也就完成了:

  

•Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 #define INFll 0x3f3f3f3f3f3f3f3f
 5 #define ll long long
 6 const int maxn=5e3+50;
 7 
 8 int n,m;
 9 char s[maxn];
10 char t[maxn];
11 struct Data
12 {
13     int fir,las;
14     Data(int fir=INF,int las=0):fir(fir),las(las){}
15 };
16 int w[maxn][maxn];
17 ll dp[maxn][maxn];
18 
19 void Preset()
20 {
21     /**
22         a[i].fir:字符 'A'+i 在串s中第一次出现的位置
23         a[i].las:字符 'A'+i 在串s中最后一次出现的位置
24         b[i].fir:字符 'A'+i 在串t中第一次出现的位置
25         b[i].las:字符 'A'+i 在串t中最后一次出现的位置
26     */
27     Data a[30],b[30];
28     for(int i=1;i <= n;++i)
29     {
30         Data &tmp=a[s[i]-'A'];
31         tmp.fir=min(tmp.fir,i);
32         tmp.las=i;
33     }
34     for(int i=1;i <= m;++i)
35     {
36         Data &tmp=b[t[i]-'A'];
37         tmp.fir=min(tmp.fir,i);
38         tmp.las=i;
39     }
40     w[0][0]=0;
41     for(int i=0;i <= n;++i)
42     {
43         for(int j=0;j <= m;++j)
44         {
45             if(i)
46             {
47                 w[i][j]=w[i-1][j];
48                 int k=s[i]-'A';
49                 if(a[k].fir == i && b[k].fir > j)///判断si是否为首次出现的
50                     w[i][j]++;
51                 if(a[k].las == i && b[k].las <= j)///判断si是否为结尾字符
52                     w[i][j]--;
53             }
54             if(j)
55             {
56                 w[i][j]=w[i][j-1];
57                 int k=t[j]-'A';
58                 if(b[k].fir == j && a[k].fir > i)///判断tj是否为首次出现的
59                     w[i][j]++;
60                 if(b[k].las == j && a[k].las <= i)///判断tj是否为结尾字符
61                     w[i][j]--;
62             }
63         }
64     }
65 }
66 ll Solve()
67 {
68     Preset();
69     dp[0][0]=0;
70     for(int i=0;i <= n;++i)
71     {
72         for(int j=0;j <= m;++j)
73         {
74             if(!(i+j))
75                 continue;
76             dp[i][j]=INFll;
77 
78             if(i)
79                 dp[i][j]=min(dp[i][j],dp[i-1][j]+w[i-1][j]);
80             if(j)
81                 dp[i][j]=min(dp[i][j],dp[i][j-1]+w[i][j-1]);
82         }
83     }
84     return dp[n][m];
85 }
86 int main()
87 {
88     int test;
89     scanf("%d",&test);
90     while(test--)
91     {
92         scanf("%s%s",s+1,t+1);
93         n=strlen(s+1);
94         m=strlen(t+1);
95 
96         printf("%lld\n",Solve());
97     }
98     return 0;
99 }
View Code

 

标签:fir,字符,1625,Color,int,Length,maxn,个字符,las
来源: https://www.cnblogs.com/violet-acmer/p/11010582.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有