看完别人的博客,我加上自己的一点理解.
对两个字符串,我们要建立坐标系观念,从而一步步找到相同的字符,最后想办法将相同的字符连续起来(间断性连续)得到我们想要的最长字符字串.
第一:我们要对相同的字符做标记.
用作表示标记的二维数组的宽度和长度多留出一行,用来存储数字0,用于后边运算.
定义两个字符数组str_x[1000],str_y[1000],整型数组arr[1001][1001]={0};
第一步分析:i=2,j=1;
str_x[j]='B',str_y[i]='B';str_x[j]==str_y[i];
所以这种情况下的字符相同个数为0,arr[2][1]==arr[1][0]+1;
加对角线上的arr,是因为再str_x[i],str_y[i]位置我们已经得到的想要的字符,如果加左边或者右边,那一个字符不就被我们用了两次吗.
第二步,如果str_x[i]!=str_y[j];arr[i][j]的左边或者右边,就可能存在字符相等时我们做的标记数字,只需要取最大即可;
比如str_x[2]='D',str_y[2]='B',两者不相等,arr[2][2]的左边就有我们做的标记1,正是str_x[1]==str_y[2];
以此类推.......
我们就可以得到类似下面的表,数字的可以表示字符串从开始到达该位置的相同字符数量(所以我们的移动要向最大数字的位置移动);
接下来,就要找出路径.
从arr末端开始找就是arr[7][6];
比较arr[i][j]对应坐标时str_x[j]跟str_y[i]是否相等,如果相等,就输出改字符,并做对角线移动到达arr[6][5];
否则(虽然该位置字符不相等,但是我们前面的操作,使得该位置的上边,或者左边具有相同的字符),就左右移动,看哪个数字大就移动到哪里,以此类推知道i==0,j==0;
最后注意int二维数组的大小;
我的电脑是对于1000*1000的二维是不会进行操作的,运行窗口一闪而过;
所以自己测试时候要小一点的数组,尤其提交时候要记得改过了;
对arr,str_x,str_y;下标操作时候注意,他们之间的下表关系可能是+1,或者-1的关系.
反正就是注意一下下表吧.
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
char arr1[1010];
char arr2[1010];
int arr[1100][1100]={0};
scanf("%s %s", arr1, arr2);
int length_x = strlen(arr1);
int length_y = strlen(arr2);
for (int i = 1; i <= length_x; i++)
{
for (int j = 1; j <= length_y;j++)
{
if (arr1[i - 1] == arr2[j - 1])
{
arr[j][i] = arr[j-1][i - 1] + 1;
}
else
{
arr[j][i] = max(arr[j - 1][i], arr[j][i - 1]);
}
}
}
int x = length_x-1, y = length_y-1;
char s[1010];
int temp = 0;
while (x>=0&&y>=0)
{
if (arr1[x] == arr2[y])
{
s[temp] = arr1[x];
temp++;
x--;
y--;
}
else if (arr[y+1][x+1] == arr[y+1][x])
{
x--;
}
else
{
y--;
}
}
for (int i = temp - 1; i >= 0; i--)
{
printf("%c", s[i]);
}
printf("\n");
return 0;
}