给定一个字符串str,删除部分字符使其变成回文串,问最少删除多少字符可以变成回文串,即最长回文串。(腾讯笔试题)
这个问题可以进行转化:
将str进行反转,得到str1,只需比较str和str1的最长公共子序列即可。求出最长公共子序列之后,将str的长度减去最长公共子序列的长度就是需要删除的字符数。
采用动态规划的方法求最长公共子序列。记字符串a(长度为i),字符串b(长度为j)的最长公共子序列为c[i][j],用一个二维数组存放。于是有下面的递推公式。
java代码(实现腾讯笔试题)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Solution s = new Solution();
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()) {
System.out.println( s.getResult(sc.nextLine()) );
}
sc.close();
}
}
class Solution {
public int getResult(String s) {
StringBuilder s1 = new StringBuilder(s);
StringBuilder s2 = new StringBuilder(s).reverse();
return s.length() - LCS(s1, s2);
}
public int LCS(StringBuilder s1, StringBuilder s2) {
int m = s1.length();
int n = s2.length();
int[][] mutrix = new int[m + 1][n + 1];
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
if(s1.charAt(i - 1) == s2.charAt(j - 1))
mutrix[i][j] = mutrix[i - 1][j - 1] + 1;
else
mutrix[i][j] = Math.max(mutrix[i - 1][j], mutrix[i][j - 1]);
}
}
return mutrix[m][n];
}
}
c语言代码(实现最长公共子序列)(递归)
#include <stdio.h>
#include <string.h>
int c[200][200];
char x[200],y[200];
int max(int a,int b){
if(a>b) return a;
return b;
}
int lcs(int lenx,int leny){
if(lenx==0||leny==0) return 0;
if(x[lenx-1]==y[leny-1]) return lcs(lenx-1,leny-1)+1;
return max(lcs(lenx,leny-1),lcs(lenx-1,leny));
}
int main(){
scanf("%s%s",x,y);
int lenx,leny;
lenx = strlen(x);
leny = strlen(y);
printf("%d",lcs(lenx,leny));
return 0;
}
c语言代码(实现最长公共子序列)(利用二维数组)
#include <stdio.h>
#include <string.h>
int c[200][200];
int max(int a,int b){
if(a>b) return a;
return b;
}
int main(){
char x[200],y[200];
scanf("%s%s",x,y);
int lenx,leny,i,j;
lenx = strlen(x);
leny = strlen(y);
for(i=1;i<=lenx;i++){
for(j=1;j<=leny;j++){
if(x[i]==y[j]) c[i][j] = c[i-1][j-1]+1;
else c[i][j] = max(c[i][j-1],c[i-1][j]);
}
}
printf("%d",c[lenx][leny]);
return 0;
}