**【题目】**对于不同的字符串,我们希望能有办法判断相似程度,我们定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法如下:
1 修改一个字符,如把“a”替换为“b”。
2 增加一个字符,如把“abdd”变为“aebdd”。
3 删除一个字符,如把“travelling”变为“traveling”。
比如,对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加和减少一个“g”的方式来达到目的。上面的两种方案,都只需要一次操作。把这个操作所需要的次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数。也就是说,“abcdefg”和“abcdef”的距离为1,相似度为1/2=0.5.
给定任意两个字符串,你是否能写出一个算法来计算出它们的相似度呢?
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String s1 = sc.next();
String s2 = sc.next();
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
int[][] dp = new int[s1.length()+1][s2.length()+1];
for(int row=1;row<=s1.length();row++){
dp[row][0]=row;
}
for(int col=1;col<=s2.length();col++){
dp[0][col]=col;
}
for(int row=1;row<=s1.length();row++){
for(int col=1;col<=s2.length();col++){
if(c1[row-1]==c2[col-1]){
dp[row][col]=dp[row-1][col-1];//相应位置相同则不+1
}else{
//不同则+1
int min1=Math.min(dp[row-1][col],dp[row][col-1])+1;
dp[row][col]=Math.min(min1,dp[row-1][col-1]+1);
}
}
}
System.out.println("1/"+(dp[s1.length()][s2.length()]+1));
}
}
}
【相似补充】公共子字符串长度
【题目】计算两个字符串的最大公共子串的长度,字符不区分大小写
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String input = sc.nextLine();
String[] s = input.split(" ");
String s1 = s[0];
String s2 = s[1];
//不区分大小写
String str1 = s1.toUpperCase();
String str2 = s2.toUpperCase();
char[] c1 = str1.toCharArray();
char[] c2 = str2.toCharArray();
//用一个二维数组来对比两个一维字符串数组,相同则该位数字在前一个基础上+1
int[][] dp = new int[c1.length+1][c2.length+1];
//先将二维数组的第一行和第一列给
for(int i=0;i<c1.length;i++){
if(c1[i]==c2[0]){
dp[i][0]=1;
}
}
for(int j=1;j<c2.length;j++){
if(c2[j]==c1[0]){
dp[0][j]=1;
}
}
int max=0;
for(int i=1;i<c1.length;i++){
for(int j=1;j<c2.length;j++){
if(c1[i]==c2[j]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=0;//不同则清零,下一个位置重新开始算
}
max = Math.max(max,dp[i][j]);
}
}
System.out.println(max);
}
sc.close();
}
}
【查找最长公共子串】
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String s1 = sc.nextLine();
String s2 = sc.nextLine();
System.out.println(fun(s1,s2));
}
sc.close();
}
public static String fun(String s1,String s2){
if(s1.length()>s2.length()){//将其变成s1短,s2长
String temp = s1;
s1 = s2;
s2 = temp;
}
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
int[][] dp = new int[s1.length()][s2.length()];
for(int i=0;i<s1.length();i++){
if(c1[i]==c2[0]){
dp[i][0]=1;
}
}
for(int j=1;j<s2.length();j++){
if(c1[0]==c2[j]){
dp[0][j]=1;
}
}
int max=0;
for(int i=1;i<s1.length();i++){//先找出最大长度max
for(int j=1;j<s2.length();j++){
if(c1[i]==c2[j]){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = 0;
}
max = Math.max(max,dp[i][j]);
}
}
//一次对比两个字符串中长为max的子串,找到短字符串s1中的第一个公共子串
for(int i=0;i<s1.length()-max+1;i++){
String ss1 = s1.substring(i,i+max);
for(int j=0;j<s2.length()-max+1;j++){
String ss2 = s2.substring(j,j+max);
if(ss1.equals(ss2)){
return ss1;
}
}
}
return null;
}
}