Description
Data Constraint
Solution
这道题考场上没想到可以倒着dp,感觉dp都白学了。 我们设出f[i][j]表示当前正确串匹配到i,原串匹配到j,i正对着j,i-n中的每个字符j-n中都可匹配的最小步数。我们现在考虑转移。 1、假设当前的j+1我们对其进行操作使它往前丢,那么f[i][j]=f[i][j+1]+1。 2、假设当前的s[i]==s1[j],那么f[i][j]=f[i+1][j+1]。 3、假设之前往前丢的点中存在s[i],就让他丢到这里,因为那么f[i][j]=f[i+1][j]. 问题是如何输出方案。 我们可以设出g[i][j]表示更新f[i][j]的是哪个点,根据上面的定义确定该点假如是要插入,就把它打上标记。我们从后往前遍历,遇到不匹配的就看他是否有标记,没有就把它丢入桶中,有就从桶中取出字符。最后我们还要处理相对位置问题,暴力的O(N^2)判一下假如发现一个点在前面输出的操作之间就+1。
Code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=
2e3+
5;
struct code{
int x,y;
}g[maxn][maxn],ans1[maxn];
int f[maxn][maxn],c[maxn][
27],d[maxn][
27],sum[
27],bz[maxn],q[
27],g1[maxn];
int m,n,i,t,j,k,l,x,y,z,xx,yy,num,num1,mi;
char s[maxn],s1[maxn];
int main(){
freopen(
"chinese.in",
"r",stdin);freopen(
"chinese.out",
"w",stdout);
scanf(
"%d\n",&m);
while (m){m--;
scanf(
"%s\n",s+
1);
scanf(
"%s\n",s1+
1);n=
strlen(s+
1);
memset(c,
0,
sizeof(c));
memset(d,
0,
sizeof(d));
memset(g1,
0,
sizeof(g1));
memset(q,
0,
sizeof(q));
memset(sum,
0,
sizeof(sum));
memset(f,
127,
sizeof(f));
for (i=n;i>=
1;i--){
for (j=
0;j<
26;j++)
d[i][j]=d[i+
1][j],c[i][j]=c[i+
1][j];
d[i][s[i]-
97]++;c[i][s1[i]-
97]++;
}
for (i=
1;i<=n+
1;i++)f[n+
1][i]=n+
1-i,g[n+
1][i].x=n+
1,g[n+
1][i].y=i+
1;
for (i=n;i>=
1;i--){
for (j=i;j>=
1;j--){
f[i][j]=f[i][j+
1]+
1,g[i][j].x=i,g[i][j].y=j+
1;
if (d[i][s[i]-
97]<=c[j][s[i]-
97]&&f[i+
1][j]<f[i][j]) f[i][j]=f[i+
1][j],g[i][j].x=i+
1,g[i][j].y=j;
if (s[i]==s1[j]&&f[i+
1][j+
1]<f[i][j]) f[i][j]=f[i+
1][j+
1],g[i][j].x=i+
1,g[i][j].y=j+
1;
}
}
printf(
"%d\n",f[
1][
1]);
x=
1;y=
1;
memset(bz,
0,
sizeof(bz));
while (f[x][y]){
xx=g[x][y].x;yy=g[x][y].y;
if (xx==x+
1 && yy==y) bz[x]=
1;
x=xx;y=yy;
}k=
0;j=n;i=n;num=
0;
while (j){
if (s1[i]==s[j]){
i--;j--;
continue;
}
if (!bz[j]) f[s1[i]-
97][++sum[s1[i]-
97]]=i,i--;
else{
ans1[++num].x=f[s[j]-
97][++q[s[j]-
97]],ans1[num].y=i+
1;
j--;k++;
}
}
for (i=
1;i<=num;i++)
for (j=i+
1;j<=num;j++)
if (ans1[i].x>ans1[j].x && ans1[i].y<ans1[j].x) ans1[j].x++;
for (i=
1;i<=num;i++)
printf(
"%d %d\n",ans1[i].x,ans1[i].y);
}
}