思路:一开始看起来没有思绪,但是仔细想想,这个问题可以转换为两个字符串求公共子序列
注意一个概念上的差异,公共子序列和公共子串。前者不要求连续,后者要求连续。
这个问题可以转换为字符串和其reverse之后的字符串求最大子序列
那么,怎么求最大子序列,考虑动态规划解决这个问题。
假设Xi=<x1,x2,……,xi>,Yj=<y1,y2,……,yj>为两个序列,用矩阵c[i,j]来记录公共子序列的个数
如果xi=yj,则c[i,j]=c[i-1,j-1]+1
如果xi不等于yj,则c[i,j]=max{c[i-1,j],max[i,j-1]}
结束条件:I或j为0,则c[i,j]=0
代码:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine()){
String line=sc.nextLine();
calculate(line);
}
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine()){
String line=sc.nextLine();
calculate(line);
}
}
private static void calculate(String str) {
StringBuilder sb=new StringBuilder();
for(int k=str.length()-1;k>=0;k--){
sb.append(str.charAt(k));
}
String reverseStr=sb.toString();
StringBuilder sb=new StringBuilder();
for(int k=str.length()-1;k>=0;k--){
sb.append(str.charAt(k));
}
String reverseStr=sb.toString();
int[][] matrix=new int[reverseStr.length()+1][str.length()+1];
String[][] flag=new String[reverseStr.length()+1][str.length()+1];
for(int x=0;x<=str.length();x++){
matrix[0][x]=0;
}
for(int y=0;y<=reverseStr.length();y++){
matrix[y][0]=0;
}
for(int i=1;i<=reverseStr.length();i++){
for(int j=1;j<=str.length();j++){
if(reverseStr.charAt(i-1)==str.charAt(j-1)){
matrix[i][j]=matrix[i-1][j-1]+1;
}else{
if(matrix[i-1][j]>matrix[i][j-1]){
matrix[i][j]=matrix[i-1][j];
}else{
matrix[i][j]=matrix[i][j-1];
}
}
}
}
System.out.println(str.length()-matrix[reverseStr.length()][str.length()]);
}
如果要打印出相同回文内容,则代码为:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine()){
String line=sc.nextLine();
calculate(line);
}
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine()){
String line=sc.nextLine();
calculate(line);
}
}
private static void calculate(String str) {
StringBuilder sb=new StringBuilder();
for(int k=str.length()-1;k>=0;k--){
sb.append(str.charAt(k));
}
String reverseStr=sb.toString();
int[][] matrix=new int[reverseStr.length()+1][str.length()+1];
String[][] flag=new String[reverseStr.length()+1][str.length()+1];
for(int x=0;x<=str.length();x++){
matrix[0][x]=0;
}
for(int y=0;y<=reverseStr.length();y++){
matrix[y][0]=0;
}
for(int i=1;i<=reverseStr.length();i++){
for(int j=1;j<=str.length();j++){
if(reverseStr.charAt(i-1)==str.charAt(j-1)){
matrix[i][j]=matrix[i-1][j-1]+1;
flag[i][j]="left-up";
}else{
if(matrix[i-1][j]>matrix[i][j-1]){
matrix[i][j]=matrix[i-1][j];
flag[i][j]="up";
}else{
matrix[i][j]=matrix[i][j-1];
flag[i][j]="left";
}
}
}
}
System.out.println(str.length()-matrix[reverseStr.length()][str.length()]);
LinkedList<Character> list=new LinkedList<>();
sequence(str,flag,reverseStr.length(),str.length(),list);
}
StringBuilder sb=new StringBuilder();
for(int k=str.length()-1;k>=0;k--){
sb.append(str.charAt(k));
}
String reverseStr=sb.toString();
int[][] matrix=new int[reverseStr.length()+1][str.length()+1];
String[][] flag=new String[reverseStr.length()+1][str.length()+1];
for(int x=0;x<=str.length();x++){
matrix[0][x]=0;
}
for(int y=0;y<=reverseStr.length();y++){
matrix[y][0]=0;
}
for(int i=1;i<=reverseStr.length();i++){
for(int j=1;j<=str.length();j++){
if(reverseStr.charAt(i-1)==str.charAt(j-1)){
matrix[i][j]=matrix[i-1][j-1]+1;
flag[i][j]="left-up";
}else{
if(matrix[i-1][j]>matrix[i][j-1]){
matrix[i][j]=matrix[i-1][j];
flag[i][j]="up";
}else{
matrix[i][j]=matrix[i][j-1];
flag[i][j]="left";
}
}
}
}
System.out.println(str.length()-matrix[reverseStr.length()][str.length()]);
LinkedList<Character> list=new LinkedList<>();
sequence(str,flag,reverseStr.length(),str.length(),list);
}
private static void sequence(String str,String[][] flag,int i,int j,LinkedList<Character> list) {
if(i==0||j==0){
StringBuilder sb=new StringBuilder();
for(Character current:list){
sb.append(current);
}
System.out.println(sb.toString());
return;
}
if(flag[i][j].equals("left-up")){
list.addFirst(str.charAt(j-1));
sequence(str,flag,i-1,j-1,list);
}else if(flag[i][j].equals("up")){
sequence(str,flag,i-1,j,list);
}else{
sequence(str,flag,i,j-1,list);
}
}
}
if(i==0||j==0){
StringBuilder sb=new StringBuilder();
for(Character current:list){
sb.append(current);
}
System.out.println(sb.toString());
return;
}
if(flag[i][j].equals("left-up")){
list.addFirst(str.charAt(j-1));
sequence(str,flag,i-1,j-1,list);
}else if(flag[i][j].equals("up")){
sequence(str,flag,i-1,j,list);
}else{
sequence(str,flag,i,j-1,list);
}
}
}
考虑了一下,求两个字符串的最长子串实际上可以通过类似的方法解决,只是这时候当xi=yj,c[i][j]=c[i-1][j-1]+1
当xi不等于yj时,c[i][j]=0.区别就在于子串要求连续,子序列不要求连续。
代码:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String line1=sc.nextLine();
String line2=sc.nextLine();
calculate(line1,line2);
}
private static void calculate(String str1,String str2){
int[][] matrix=new int[str1.length()+1][str2.length()+1];
for(int x=0;x<=str1.length();x++){
matrix[x][0]=0;
}
for(int y=0;y<=str2.length();y++){
matrix[0][y]=0;
}
int max=-1,x=0,y=0;
for(int i=1;i<=str1.length();i++){
for(int j=1;j<=str2.length();j++){
if(str1.charAt(i-1)==str2.charAt(j-1)){
matrix[i][j]=matrix[i-1][j-1]+1;
}else{
matrix[i][j]=0;
}
if(matrix[i][j]>max){
max=matrix[i][j];
x=i;
y=j;
}
}
}
System.out.println(x+" "+y);
LinkedList<Character> list=new LinkedList<>();
subString(matrix,x,y,str1,list);
}
private static void subString(int[][] matrix,int i,int j,String str,LinkedList<Character> list){
if(matrix[i][j]==0){
StringBuilder sb=new StringBuilder();
for(Character c:list){
sb.append(c);
}
System.out.println(sb.toString());
return;
}
list.addFirst(str.charAt(i-1));
subString(matrix,i-1,j-1,str,list);
}
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String line1=sc.nextLine();
String line2=sc.nextLine();
calculate(line1,line2);
}
private static void calculate(String str1,String str2){
int[][] matrix=new int[str1.length()+1][str2.length()+1];
for(int x=0;x<=str1.length();x++){
matrix[x][0]=0;
}
for(int y=0;y<=str2.length();y++){
matrix[0][y]=0;
}
int max=-1,x=0,y=0;
for(int i=1;i<=str1.length();i++){
for(int j=1;j<=str2.length();j++){
if(str1.charAt(i-1)==str2.charAt(j-1)){
matrix[i][j]=matrix[i-1][j-1]+1;
}else{
matrix[i][j]=0;
}
if(matrix[i][j]>max){
max=matrix[i][j];
x=i;
y=j;
}
}
}
System.out.println(x+" "+y);
LinkedList<Character> list=new LinkedList<>();
subString(matrix,x,y,str1,list);
}
private static void subString(int[][] matrix,int i,int j,String str,LinkedList<Character> list){
if(matrix[i][j]==0){
StringBuilder sb=new StringBuilder();
for(Character c:list){
sb.append(c);
}
System.out.println(sb.toString());
return;
}
list.addFirst(str.charAt(i-1));
subString(matrix,i-1,j-1,str,list);
}
}