上学期的期末考为了应付考试,只是把每种算法都理解了一遍,但是并没有具体的代码实现。现在开始抽空慢慢实现这些算法。
代码实现:
import java.util.Scanner; public class Main2 { public static void main(String[] args){ //从键盘输入第一个字符串 Scanner in=new Scanner(System.in); String string1=in.nextLine(); //从键盘输入第二个字符串 String string2=in.nextLine(); in.close(); //关闭输入 char[] chars1=string1.toCharArray(); char[] chars2=string2.toCharArray(); int length1=string1.length(); int length2=string2.length(); /*这里要加1,因为要构造的那个二维数组是行和列都是从0比到6的 会比原字符串的长度多1 */ int dp[][]=new int[length1+1][length2+1]; /*后面为了对齐方向箭头打印位置初始从1开始打印,所以这里长度加2,避免数组溢出*/ char b[][]=new char[length1+2][length2+1]; /*构造第一排和第一列的所有的0*/ for(int i=0; i<=length1;i++){ dp[i][0]=0; } for(int j=1;j<=length2;j++){ dp[0][j]=0; } //自底向上计算 for(int i=1;i<=length1;i++){ for(int j=1;j<=length2;j++){ if(chars1[i-1]==chars2[j-1]){ dp[i][j]=dp[i-1][j-1]+1; b[i][j]='↖'; }else if(dp[i][j-1]>dp[i-1][j]){ dp[i][j]=dp[i][j-1]; b[i][j]='←'; }else{ dp[i][j]=dp[i-1][j]; b[i][j]='↑'; } } } /*输出*/ for(int i=0;i<=length1;i++){ for(int j=0;j<=length2;j++){ System.out.print(dp[i][j]+" "); } System.out.println(); for(int j=0;j<=length2;j++){ System.out.print(b[i+1][j]+" ");//为了对齐方向箭头,从第二行开始逐行打印 } System.out.println(); } } }
结果:
这里有个算法的衍生,就是求构造回文需要删除的最小字符个数。其实只需要将一个字符串和它的逆序字符串求公共最长子串就可以了。
import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner in=new Scanner(System.in); while(in.hasNext()){ //循环输入 String string=in.nextLine(); char[] chars=string.toCharArray(); int length=string.length(); int dp[][]=new int[length+1][length+1]; /*构造第一排和第一列的所有的0*/ for(int i=0; i<length+1;i++){ dp[i][0]=0; dp[0][i]=0; } //自底向上计算 for(int i=1;i<=length;i++){ for(int j=1;j<=length;j++){ if(chars[i-1]==chars[length-j]){ dp[i][j]=dp[i-1][j-1]+1; }else if(dp[i][j-1]>dp[i-1][j]){ dp[i][j]=dp[i][j-1]; }else{ dp[i][j]=dp[i-1][j]; } } } //输出构造回文需要删除的最少字符的个数 System.out.println(length - dp[length][length]); } } }