问题陈述:给定两个相等长度的字符串a和b,可以构造的最长字符串(S)是什么,使得S是a和b的子节点。字符串x被称为字符串y的子节点,如果x可以通过从y中删除0个或多个字符来形成(即,找到最长的公共子序列)。
输入:两个字符串a和b,换行符分隔它们。
约束:所有字符都是大写的,位于ASCII值65-90之间。字符串a和b的最大长度为5000。
输出格式:字符串S的长度。
我的问题是我在一个测试案例中遇到了分段错误。 SOMEOE PLZ告诉我为什么?
这是我在C代码中的代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int max(int a, int b)
{
return (a>b)?a:b;
}
int lcs(char *X, char *Y, int x, int y)
{
int L[x+1][y+1];
int i,j;
for(i=0 ; i<=x ; i++)
{
for(j=0 ; j<=y ; j++)
{
if(i==0 || j==0)
L[i][j] = 0;
else if(X[i-1] == Y[j-1])
{
L[i][j] = 1 + L[i-1][j-1];
}
else
L[i][j] = max(L[i-1][j],L[i][j-1]);
}
}
return L[x][y];
}
int main() {
char a[5000],b[5000];
scanf("%s",a);
scanf("%s",b);
int lenA, lenB;
lenA = strlen(a);
lenB = strlen(b);
printf("%d",lcs(a,b,lenA,lenB));
return 0;
}
答案 0 :(得分:3)
我认为有三个可能的原因:
您的输入太大了。 scanf()不会检测到,但您可以指定要读取的最大字符串长度:
的scanf(&#34;%4999s&#34;,α);
您尝试读取一个包含5000个字符的字符串,并将终止0的字符串读入5000个字符的数组中。这意味着终止0将覆盖某些任意内存,或者可能被下一次调用scanf覆盖。因此,只需将数组定义为大1字节。可以肯定的是,将它们定义为大2个字节,(a [5002],b [5002]),允许扫描5001个字符,检查扫描长度并抱怨它是否为5001.听起来很偏执,但显然出现了问题,因此你的代码应该准备好发现错误。
L [x + 1] [y + 1]可能会导致相当大的数组。想象一下,你扫描两个5000字节的字符串,终止0会丢失,因为你的数组太短,而strlen会导致5012和10012.在这种情况下,你想在堆栈上分配200 MB。这非常多,可能会失败。即使您很幸运,并且您的字符串已正确终止,您仍可能需要100 MB的堆栈。这不是堆栈的工作方式。
顺便说一下 - 你正在实现Levenstein算法的变体 - Levenstein测量两个字符串之间的差异,同时测量公共部分,这只是同一个问题的另一个视图。你知道它可以在没有5001x5001矩阵的情况下实现吗?它足以在堆栈上有3x5001整数。为了计算结果矩阵的下一行,您只需要前两行,这意味着它足以在堆栈上保留3行矩阵。而这3行将适合。