uva1371Period (二分+DP)

Posted konjak魔芋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva1371Period (二分+DP)相关的知识,希望对你有一定的参考价值。

题意:

  给出两个字符串A,B将B分解成若干个子字符串,然后每个子字符串都要经过编辑变成字符串A,所有子串中编辑最多的次数即为当前状态下的最大编辑次数,要求求最小的最大编辑次数。

  编辑操作包括修改、删除和插入。(|A|<=5000,|B|<=50)

 

分析:

  因为A的长度较大,直接算出A每个区间对应B的编辑次数的方法是不可取的。因为是求最大值最小化,可以想到二分答案然后判断。

  判断的时候用DP,dp[i][j]表示到1~i的字符串匹配到j的最大编辑次数。当dp[i][m]<=mid时(mid为二分出来的当前答案),就可以将dp[i][0] 置0,表示做为起点(因为此时可以在i后面分段)。

  打代码的时候出现了一个问题,当我dp[i][m]<=mid时,我把dp[i][0] 置0的同时,还把dp[i]的其他值全部置成INF,这样做是有问题的。比如,x=abcdabcabb,y=abc,当mid=1时,前面两个字符ab的编辑长度刚好为一,此时我直接把ab分成一段了,这样导致我把第三个字符c扔在一边。其实把abc一起放成一段更好。问题就出在我把dp[i][0] 置0的同时还把dp[i]的其他值全部置成INF。这样做相当于默认我把i前面的分成一段,但事实上或许再加一个字符编辑距离仍然不超过mid,这样可能会使后面的答案更优而我却没有找到最优解,于是就产生判断错误。所以只需把dp[i][0] 置0即可,这样子就表示我们可以把i前面的字符分成一段,当然也可以再加一些字符再分成一段。

 

代码如下:

技术分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<iostream>
 6 using namespace std;
 7 #define Maxn 5010
 8 #define Maxm 60
 9 
10 char a[Maxn],b[Maxm];
11 int n,m;
12 
13 int f[Maxn][Maxm];
14 
15 int mymin(int x,int y) {return x<y?x:y;}
16 
17 bool dp(int x)
18 {
19     memset(f,63,sizeof(f));
20     for(int i=0;i<=m;i++) f[0][i]=i;
21     for(int i=1;i<=n;i++)
22     {
23         for(int j=1;j<=m;j++)
24         {
25             if(a[i]==b[j]) f[i][j]=mymin(f[i][j],f[i-1][j-1]);
26             else f[i][j]=mymin(f[i][j],f[i-1][j-1]+1);
27             f[i][j]=mymin(f[i][j],f[i-1][j]+1);
28             f[i][j]=mymin(f[i][j],f[i][j-1]+1);
29         }
30         if(f[i][m]<=x)
31         {
32             if(i==n) return 1;
33             f[i][0]=0;
34         }
35         if(i==n) return 0;
36     }
37 }
38 
39 void ffind()
40 {
41     scanf("%s%s",b+1,a+1);
42     n=strlen(a+1);m=strlen(b+1);
43     int l=0,r=n;
44     while(l<r)
45     {
46         int mid=(l+r)>>1;
47         if(dp(mid)) r=mid;
48         else l=mid+1;
49     }
50     printf("%d\n",l);
51 }
52 
53 int main()
54 {
55     int T;
56     scanf("%d",&T);
57     while(T--)
58     {
59         ffind();
60     }
61     return 0;
62 }
uva1371

2016-03-06 16:47:51

 

貌似已经看到很多题二分加DP了~

 

以上是关于uva1371Period (二分+DP)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 1371E2 - Asterism (二分)

UVA 1328 - Period (KMP)

UVA1328 Period

ACM/ICPC 之 DP进阶(51Nod-1371(填数字))

训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

51NOD 1371