腾讯面试题-回文构造
算法,腾讯,面试2016-07-17
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
abcda
google
2
2
首先求s的反串rs,然后对s和rs求最长公共子序列,要删除的字符个数就是LCS.
public class ComSubstr {
public static void main(String[] arg) {
String a = "blog.csdn.net";
String b = "csdn.blogt";
comSubstring(a, b);
}
private static void comSubstring(String str1, String str2) {
char[] a = str1.toCharArray();
char[] b = str2.toCharArray();
int a_length = a.length;
int b_length = b.length;
int[][] lcs = new int[a_length + 1][b_length + 1];
// 初始化数组
for (int i = 0; i <= b_length; i++) {
for (int j = 0; j <= a_length; j++) {
lcs[j][i] = 0;
}
}
for (int i = 1; i <= a_length; i++) {
for (int j = 1; j <= b_length; j++) {
if (a[i - 1] == b[j - 1]) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
}
if (a[i - 1] != b[j - 1]) {
lcs[i][j] = lcs[i][j - 1] > lcs[i - 1][j] ? lcs[i][j - 1]
: lcs[i - 1][j];
}
}
}
// 输出数组结果进行观察
for (int i = 0; i <= a_length; i++) {
for (int j = 0; j <= b_length; j++) {
System.out.print(lcs[i][j]+",");
}
System.out.println("");
}
// 由数组构造最小公共字符串
int max_length = lcs[a_length][b_length];
char[] comStr = new char[max_length];
int i =a_length, j =b_length;
while(max_length>0){
if(lcs[i][j]!=lcs[i-1][j-1]){
if(lcs[i-1][j]==lcs[i][j-1]){//两字符相等,为公共字符
comStr[max_length-1]=a[i-1];
max_length--;
i--;j--;
}else{//取两者中较长者作为A和B的最长公共子序列
if(lcs[i-1][j]>lcs[i][j-1]){
i--;
}else{
j--;
}
}
}else{
i--;j--;
}
}
System.out.print("最长公共字符串是:");
System.out.print(comStr);
}
}
问题】 求两字符序列的最长公共字符子序列
并不要求子串(字符串一)的字符必须连续出现在字符串二中。
设序列X=
由最长公共子序列问题的最优子结构性质可知,要找出X=
例如,在计算X和Y的最长公共子序列时,可能要计算出X和Yn-1及Xm-1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。
与矩阵连乘积最优计算次序问题类似,我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。其中Xi=<x1, x2, …, xi>,Yj=<y1, y2, …, yj>。
public class ComSubstr {
public static void main(String[] arg) {
String a = "blog.csdn.net";
String b = "csdn.blogt";
comSubstring(a, b);
}
private static void comSubstring(String str1, String str2) {
char[] a = str1.toCharArray();
char[] b = str2.toCharArray();
int a_length = a.length;
int b_length = b.length;
int[][] lcs = new int[a_length + 1][b_length + 1];
// 初始化数组
for (int i = 0; i <= b_length; i++) {
for (int j = 0; j <= a_length; j++) {
lcs[j][i] = 0;
}
}
for (int i = 1; i <= a_length; i++) {
for (int j = 1; j <= b_length; j++) {
if (a[i - 1] == b[j - 1]) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
}
if (a[i - 1] != b[j - 1]) {
lcs[i][j] = lcs[i][j - 1] > lcs[i - 1][j] ? lcs[i][j - 1]
: lcs[i - 1][j];
}
}
}
// 输出数组结果进行观察
for (int i = 0; i <= a_length; i++) {
for (int j = 0; j <= b_length; j++) {
System.out.print(lcs[i][j]+",");
}
System.out.println("");
}
// 由数组构造最小公共字符串
int max_length = lcs[a_length][b_length];
char[] comStr = new char[max_length];
int i =a_length, j =b_length;
while(max_length>0){
if(lcs[i][j]!=lcs[i-1][j-1]){
if(lcs[i-1][j]==lcs[i][j-1]){//两字符相等,为公共字符
comStr[max_length-1]=a[i-1];
max_length--;
i--;j--;
}else{//取两者中较长者作为A和B的最长公共子序列
if(lcs[i-1][j]>lcs[i][j-1]){
i--;
}else{
j--;
}
}
}else{
i--;j--;
}
}
System.out.print("最长公共字符串是:");
System.out.print(comStr);
}
}
0,0,0,0,0,0,1,2,2,2,2,
0,0,0,0,0,0,1,2,3,3,3,
0,0,0,0,0,0,1,2,3,4,4,
0,0,0,0,0,1,1,2,3,4,4,
0,1,1,1,1,1,1,2,3,4,4,
0,1,2,2,2,2,2,2,3,4,4,
0,1,2,3,3,3,3,3,3,4,4,
0,1,2,3,4,4,4,4,4,4,4,
0,1,2,3,4,5,5,5,5,5,5,
0,1,2,3,4,5,5,5,5,5,5,
0,1,2,3,4,5,5,5,5,5,5,
0,1,2,3,4,5,5,5,5,5,6,
最长公共字符串是:csdn.t
## 我的微信二维码如下,欢迎交流讨论 ##
参考:
http://www.nowcoder.com/test/question/done?tid=3778580&qid=44802
http://www.voidcn.com/blog/Do_Know/article/p-5978576.html