51nod 1006最大公共字符字串(仅供参考,不支持AC)

51nod 1006题最大公共字符串

看完别人的博客,我加上自己的一点理解.

对两个字符串,我们要建立坐标系观念,从而一步步找到相同的字符,最后想办法将相同的字符连续起来(间断性连续)得到我们想要的最长字符字串.

第一:我们要对相同的字符做标记.

用作表示标记的二维数组的宽度和长度多留出一行,用来存储数字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;
}

猜你喜欢

转载自blog.csdn.net/qq_40989705/article/details/81176712