A - 编辑距离
题目
题意:替换、插入、删除。问需要变换多少次可将字符串转换为目的串。
思路:遍历两个字符串;
相同:在a删除一个字符去匹配b、a添加一个字符去匹配b、a不变的时候去匹配b中选择一个最小的。
不同:在a删除一个字符去匹配b、a添加一个字符去匹配b、a替换一个字符去匹配b中选择一个最小的。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <math.h>
#include <cstdio>
#include <cstdlib>
#define INF 0x3f3f3f3f
using namespace std;
int m[1100][1100];
char a[1100],b[1100];
int fun(int a,int b,int c)
{
a=min(a,b);
return min(a,c);
}
int main()
{
scanf("%s%s",a+1,b+1);
int lena,lenb,i,j;
lena=strlen(a+1);
lenb=strlen(b+1);
for(i=0; i<=lena; i++)
for(j=0; j<=lenb; j++)
m[i][j]=INF;
for(i=0; i<=lena; i++)
m[i][0]=i;
for(i=0; i<=lenb; i++)
m[0][i]=i;
for(i=1; i<=lena; i++)
for(j=1; j<=lenb; j++)
{
if(a[i]==b[j])
m[i][j]=fun(m[i-1][j]+1,m[i][j-1]+1,m[i-1][j-1]);
else
m[i][j]=fun(m[i-1][j]+1,m[i][j-1]+1,m[i-1][j-1]+1);
}
cout<<m[lena][lenb]<<endl;
return 0;
}
B - LCS 裸题
题目
题意:输出两个字符串的最长公共子序列。
思路:先求出dp数组,根据dp数组倒着遍历一遍将字符串找出来。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
int m[1100][1100];
int main()
{
char a[1100],b[1100];
stack<char> s;
int lena,lenb,i,j;
scanf("%s%s",a+1,b+1);
lena=strlen(a+1);
lenb=strlen(b+1);
memset(m,0,sizeof(m));
for(i=1; i<=lena; i++)
for(j=1; j<=lenb; j++)
if(a[i]==b[j])
m[i][j]=m[i-1][j-1]+1;
else
m[i][j]=max(m[i-1][j],m[i][j-1]);
for(i=lena,j=lenb; i>=1, j>=1;)
{
if(a[i]==b[j])
{
s.push(a[i]);
i--;
j--;
}
else if(m[i-1][j]>m[i][j-1])
i--;
else
j--;
}
while(!s.empty())
{
cout<<s.top();
s.pop();
}
cout<<endl;
return 0;
}
C - 编辑距离++
题目
题意:给一个母串(循环的)。再给几个字符串(长度不超过10)。问这几个字符串需要变化多少次,可以变成母串的子串。输出这个字符串和变换次数。
思路:因为母串是循环的,且给出的字符串长度不超过10,因此可将母串延长10个字符,就可达到循环的效果。
#include <iostream>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int dp[20][110000];
int fun(char *s,char *str,int len,int lenstr)
{
int i,j;
int mi=INF;
for(i=0; i<=len; i++)
dp[i][0]=i;
for(i=1; i<=len; i++)
{
for(j=1; j<=lenstr; j++)
{
dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+((s[i-1]==str[j-1])?0:1));
if(i==len)
mi=min(mi,dp[i][j]);
}
}
return mi;
}
int main()
{
char str[110000];
while(cin>>str)
{
memset(dp,0,sizeof(dp));
char s[20][20];
int lenstr,len;
lenstr=strlen(str);
int n,i,j;
for(i=0; i<=10; i++)
str[lenstr+i]=str[i];
str[i]='\0';
int re=INF,index=0;
cin>>n;
for(i=0; i<n; i++)
{
cin>>s[i];
int mi=INF;
len=strlen(s[i]);
if(len>lenstr)
for(j=0; j<lenstr; j++)
mi=min(mi,fun(s[i],str+j,len,lenstr));
else
mi=min(mi,fun(s[i],str,len,lenstr+min(10,lenstr)));
if(mi<re||(re==mi)&&(strcmp(s[index],s[i])>0))
{
re=mi;
index=i;
}
}
cout<<s[index]<<' '<<re<<endl;
}
return 0;
}
E - A Prosperous Lot
题目
题意:0469有一个圈,8有两个圈,12357没有圈,输入k代表圈的个数,输出一个符合的数字
思路:18个8有36个圈,在不超过18位的数字中,18个8的圈数最多,因此若k>36就输出-1。#
#include <iostream>
using namespace std;
int main()
{
int k;
while(cin>>k)
{
if(k>36)
cout<<"-1"<<endl;
else{
int i;
for(i=0;i<k/2;i++)
cout<<'8';
if(k&1)
cout<<'9';
cout<<endl;
}
}
return 0;
}
F - A Compatible Pair
题目
题意:给定两个数列 A、B ,元素个数分别为 n、m (2<=n,m<=50) 。数列中所有元素大小均在 -10 ^{9}到10 ^{9}之间。
现要求在 AA数列中删掉一个元素,使得 A 中任一元素和 B 中任一元素相乘的共(n−1)×m 种可能的值中的最大值最小。输出该最大值。
思路:枚举。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
ll a[55],b[55];
int main()
{
int n,m;
ll a[55],b[55],c[55];
cin>>n>>m;
for(int i=0; i<n; ++i)
cin>>a[i];
for(int i=0; i<m; ++i)
cin>>b[i];
for(int i=0; i<n; ++i)
{
c[i]=a[i]*b[0];
for(int j=1; j<m; ++j)
c[i]=max(c[i],a[i]*b[j]);
}
sort(c,c+n);
cout<<c[n-2]<<endl;
return 0;
}