输入两串字符串,利用函数还有指针,找出两串字符串相同的字符段,并输出相同字符串的起始位置。 例:输入fu#stuentgh和student,函数返回值为4,若没有,返回-1. 用
时间: 2025-03-08 07:10:13 浏览: 37
<think>嗯,我现在要解决这个问题:输入两个字符串,找出它们相同的字符段,并输出相同字符串的起始位置。比如输入“fu#stuentgh”和“student”,函数返回4。如果没找到就返回-1。我得用C语言,还要用函数和指针来处理。这个问题看起来像是字符串匹配的问题,可能需要比较两个字符串的所有可能的子串。
首先,我得理解题目要求。题目中的“相同的字符段”应该是指最长的公共子串还是任意长度的公共子串?例子中,“student”在第一个字符串中的位置是从第4个字符开始(假设索引从0开始还是从1开始?例子返回4,可能用户指的是从0开始的话,比如原字符串中“s”的位置是4?比如原例子的第一个字符串是“fu#stuentgh”,可能分解一下:f, u, #, s, t, u, e, n, t, g, h。那“s”的位置是索引3,但例子返回4,可能用户这里的起始位置是从1开始计数的。所以需要明确起始位置的计数方式。但可能用户希望的是,当两个字符串有连续相同的部分时,找到第一个出现的位置。比如在第一个字符串中,可能存在多个匹配的位置,要找到第一个出现的位置。
假设例子中的第一个字符串是“fu#stuentgh”,第二个是“student”。那么第一个字符串中的“stuent”可能和第二个字符串的“student”部分匹配。但是例子中的返回值为4,可能起始位置是4(从0开始的话,s的位置是3,但输出4,可能用户例子中的起始位置是从1开始?或者可能我哪里理解错了。需要再仔细看例子。
比如原例子的第一个输入是“fu#stuentgh”,第二个是“student”,函数返回4。那假设第一个字符串中的相同部分是“stu”,或者更长的部分?或者可能“stuent”和“student”的最长公共子串?
或者可能例子中的正确匹配是“stu”后面的部分?比如第一个字符串中的“stuent”和第二个字符串的“student”是否有重叠?比如第二个字符串是s-t-u-d-e-n-t,而第一个字符串中的s-t-u-e-n-t。可能这里有一个共同的子串比如“stu”或者“tudent”之类的?或者可能例子中的正确起始位置是4,可能索引从0开始的话,原字符串中的“s”在位置3,那可能例子中的起始位置是从1开始计数,所以返回4。或者可能原例子中的两个字符串的公共部分是“tudent”?比如第一个字符串中的“t”在某个位置?
可能我需要先不管例子,先想如何解决这个问题的一般情况。
思路大概是:对于两个字符串s1和s2,找出最长的公共子串,并返回其在s1中的起始位置。如果没有,返回-1。或者题目是否要求只要存在至少一个公共字符段(不管长度?)或者要求最长的那个?或者只要存在任意长度的连续相同字符段?题目中的例子中的返回值是4,可能只要找到第一个出现的位置,不管长度,但可能题目要求的是最长的公共子串,或者找到第一个匹配的位置。
根据题目描述中的例子,输入两个字符串,函数返回相同字符段的起始位置。例如,输入第一个字符串“fu#stuentgh”和“student”,输出4。可能这里的相同字符段是“stu”,即第一个字符串中的s的位置是索引3,但返回4,可能起始位置是1-based的。所以原例子中的s在第一个字符串中的位置是第4个字符(假设原字符串的索引是0-based的话,f是0,u是1,#是2,s是3,所以返回3的话,如果用户给出的例子返回4,可能用户期望的是1-based的索引。所以可能需要将找到的位置+1返回?或者例子可能有其他情况,比如实际匹配的是更长的子串?
可能需要更详细的分析例子。比如,假设第一个字符串是"fu#stuentgh",分解为字符数组:
索引:0:f,1:u,2:#,3:s,4:t,5:u,6:e,7:n,8:t,9:g,10:h
第二个字符串是"student",分解为s(0),t(1),u(2),d(3),e(4),n(5),t(6)
现在,要找两个字符串中的最长公共子串,并返回在第一个字符串中的起始位置。例如,可能子串是“stu”(s在第一个字符串的位置3,但第二个字符串中的s是起始位置0),但可能最长的是“tudent”吗?或者可能不是。例如,第一个字符串中的stuent(索引3到8:s,t,u,e,n,t)和第二个字符串的student(s,t,u,d,e,n,t)可能有部分重叠。例如,可能第一个字符串中的“stu”和第二个字符串中的“stu”匹配,那么起始位置是3(0-based)或者4(1-based)。而例子中返回4,说明可能起始位置是1-based的。所以在代码中需要返回第一个字符串中的起始位置(1-based)。
所以问题转化为:在两个字符串中寻找最长的公共连续子串,并返回该子串在第一个字符串中的起始位置(1-based),如果有多个相同长度的最长子串,则返回第一个出现的。如果没有,返回-1。
那如何实现这个呢?
可能的步骤是:
1. 遍历第一个字符串的所有可能的子串起点和终点。
2. 对于每个子串,检查它是否存在于第二个字符串中。
3. 记录所有存在的子串中最长的那个,并且记录其在第一个字符串中的起始位置。
4. 如果有多个相同长度的最长子串,选第一个出现的。
5. 如果没有公共子串,则返回-1。
但是这样的方法时间复杂度很高,尤其是当字符串很长的时候。但是对于这个问题,可能用户给出的例子中的字符串长度不大,所以可以用这种方法。
或者,有没有更高效的算法?比如动态规划的方法,求最长公共子串的长度,并记录位置。
动态规划方法通常是用来求最长公共子串的长度的,并且可以记录位置。例如,构造一个二维数组dp[i][j]表示以s1的第i个字符和s2的第j个字符结尾的最长公共子串的长度。当s1[i-1] == s2[j-1]时,dp[i][j] = dp[i-1][j-1] + 1。否则,dp[i][j] =0。这样,遍历所有i和j,记录最大的dp[i][j]的值,以及对应的位置。
这个方法的时间复杂度是O(n*m),其中n和m是两个字符串的长度。这可能对于较长的字符串来说效率较低,但对于一般情况可能可以接受。
但是,题目中要求的不是最长公共子串的长度,而是找到两个字符串中相同的字符段(可能只要存在至少一个公共子串,或者最长的一个?例子中的返回值是4,可能对应的是第一个出现的公共子串的起始位置,而不一定是最长的。需要根据例子来分析。
假设在例子中,第一个字符串中的“stuent”和第二个字符串中的“student”可能存在的最长公共子串是“stu”(长度3),或者可能是“ent”(长度3),或者其他?或者可能最长的是“tent”?
需要具体比较:
例如,第一个字符串中的s在位置3,第二个字符串中的s在位置0。当比较的时候,s相同,那么看后面的字符是否相同。第一个字符串的t在位置4,第二个字符串的t在位置1。相同。然后第一个字符串的u在位置5,第二个字符串的u在位置2。相同。然后第一个字符串的e在位置6,第二个字符串的d在位置3,不相同。所以此时公共子串是stu,长度3,起始位置在第一个字符串中的3(0-based),即返回3+1=4?所以用户例子中的结果正确。
所以问题转化为找到最长的公共子串,并返回其在第一个字符串中的起始位置(1-based)。如果有多个最长公共子串,返回第一个出现的起始位置。
所以,现在需要实现这个逻辑。使用动态规划的方法来找到最长公共子串的起始位置。
那么,如何记录起始位置呢?
在动态规划的过程中,每次当dp[i][j]的值大于当前的最大值时,记录下此时的i的位置,即第一个字符串中的结束位置,然后根据长度和结束位置来计算起始位置。
例如,假设最大长度是max_len,结束位置在i-1(因为dp数组的索引i对应s1的第i个字符,s1的索引是0-based的话),那么起始位置是i - max_len。
所以,在代码中,可以用动态规划来记录最长公共子串的长度和其在s1中的结束位置,然后计算起始位置。
然后,如果存在多个相同长度的最长子串,取第一个出现的,这可能需要调整动态规划的记录方式,确保在出现更早的起始位置时,优先记录。
或者,当找到同样长度的子串时,保留较早出现的位置。
综上,步骤大概是:
- 初始化变量max_len来记录最长公共子串的长度,start_pos记录其在s1中的起始位置(0-based)。
- 创建一个二维数组dp,大小为 (len1+1) x (len2+1),初始化为0。
- 遍历i从1到len1,遍历j从1到len2:
- 如果s1[i-1] == s2[j-1],则dp[i][j] = dp[i-1][j-1] +1。
- 否则,dp[i][j] =0。
- 如果dp[i][j] > max_len,则更新max_len为dp[i][j],并记录此时的起始位置i - max_len。
- 遍历结束后,如果max_len >0,则返回起始位置+1(转换为1-based),否则返回-1。
例如,在例子中:
s1是"fu#stuentgh",s2是"student"。
当i=3(s1[3]是's'),j=0(s2[0]是's'),此时dp[4][1]=1(因为s1[3]==s2[0]),然后i=4,j=1,s1[4]是't',s2[1]是't',此时dp[5][2] = dp[4][1]+1=2。接着i=5,j=2,s1[5]是'u',s2[2]是'u',所以dp[6][3]=3。此时max_len变成3,起始位置是i - max_len =5 -3 =2?或者 i=6(对应s1的第6个字符?可能需要仔细看索引。
或者,假设i和j对应的是s1的i-1和s2的j-1的字符。例如,当i=4时,s1[i-1]是索引3的字符,即's'?
或者,可能我的索引处理有问题,需要仔细分析。
可能在这个例子中,i和j的循环是从1到len1和len2。例如,s1的长度是len1,s2是len2。对于i=1到len1,j=1到len2,对应的字符是s1[i-1]和s2[j-1]。
当比较到i=4(s1[3]是's'),j=1(s2[0]是's')时,相等,所以dp[4][1] = dp[3][0] +1 = 1。此时max_len变为1,起始位置是i - max_len =4-1=3,对应的s1中的位置是3(0-based),即返回4(1-based)。
接下来,i=5,j=2,s1[4]是't',s2[1]是't',此时dp[5][2] = dp[4][1]+1=2。此时max_len=2,起始位置是5-2=3(0-based)。
i=6,j=3,s1[5]是'u',s2[2]是'u',所以dp[6][3] =3,max_len=3,起始位置是6-3=3(0-based)。对应的起始位置3(0-based)即返回4(1-based)。
这样,例子中的返回值是正确的。
所以这个动态规划的方法可以找到最长公共子串的长度和起始位置。
现在需要将这个方法用C语言实现,用函数和指针来处理。
函数的参数应该是两个字符串,返回值为int,即起始位置(1-based)或-1。
但需要注意,题目中的例子返回的是4,即起始位置是3(0-based)转为4(1-based)。所以在计算的时候,返回的是起始位置+1。
所以,现在需要实现:
函数原型:int find_common_segment(char *s1, char *s2);
函数内部:
- 计算两个字符串的长度len1和len2。
- 创建二维数组dp,尺寸为(len1+1) x (len2+1)。
- 初始化max_len和start_pos为0和-1.
- 遍历i从1到len1:
遍历j从1到len2:
if s1[i-1] == s2[j-1],则dp[i][j] = dp[i-1][j-1] +1.
否则,dp[i][j]=0.
if dp[i][j] > max_len:
max_len = dp[i][j]
start_pos = i - max_len
- 最后,如果max_len >0,返回start_pos +1(转为1-based),否则返回-1.
但需要注意,如果有多个相同长度的子串,应该返回第一个出现的。例如,当在后面的位置有一个同样长度的子串时,是否会被覆盖?比如,如果之后出现同样长度的子串,此时start_pos会被更新为更后面的位置吗?
比如,假设前面的最长是3,后面又出现一个3长度的,那么start_pos会被后面的i - max_len覆盖,导致返回的是后面出现的起始位置。这与题目中的要求是否冲突?
题目中的例子可能需要返回第一个出现的最长子串的起始位置。因此,在动态规划中,当遇到同样长度的子串时,应该保留原来的start_pos,而不是更新。因此,在代码中,当dp[i][j]等于当前max_len时,不更新start_pos。只有当dp[i][j]严格大于max_len时,才更新。
例如,初始max_len是0。当找到一个长度为1的子串,max_len变成1,start_pos更新。之后,如果找到一个长度为1的子串,但出现的位置更早,那么会被忽略,因为max_len不会改变。所以这样得到的start_pos是第一个最长的子串的起始位置吗?
或者,可能当max_len被多次达到同样的值时,start_pos会被更新为最后出现的位置?
比如,假设有一个更长的子串出现在后面,那么没问题。但是如果出现同样长度的子串在更早的位置,是否会被覆盖?
例如,假设两个相同长度的子串,第一个出现在位置3,第二个出现在位置5。动态规划的方法会因为第一次发现长度为3的时候记录位置3,之后当再次遇到长度为3的子串时,max_len没有改变,所以start_pos不会被更新。这样,返回的是第一次出现的最长子串的位置,这可能符合题目要求。
所以代码中的处理是正确的,会返回最长子串中第一个出现的起始位置。
那这样的话,代码的逻辑是正确的。
现在,如何在C语言中实现这个动态规划?
需要注意二维数组的创建。由于C语言中无法直接声明动态大小的二维数组,可能需要使用一维数组模拟,或者使用指针数组。或者,如果字符串长度不是特别大,可以使用栈上的数组,但通常更安全的方式是使用堆内存。
例如,假设两个字符串的长度分别为len1和len2,那么需要创建一个二维数组dp[len1+1][len2+1]。这可能需要动态分配内存。例如:
int **dp = (int **)malloc((len1 +1) * sizeof(int *));
for (int i=0; i<=len1; i++) {
dp[i] = (int *)malloc((len2 +1) * sizeof(int));
}
然后初始化所有元素为0。
或者,为了优化空间,可以用一维数组,因为每次计算dp[i][j]只需要dp[i-1][j-1],所以可以用一维数组,并不断更新。例如,可以使用一个一维数组prev,然后每次迭代时保存当前行的数据,并覆盖之前的数据。这样可以减少空间复杂度到O(min(len1, len2))。但可能对于代码的编写来说更复杂。
不过,对于这个问题来说,可能直接使用二维数组更直观。
另外,需要注意字符串的长度可能为0的情况,需要处理边界条件。
现在,编写函数的大致步骤:
1. 计算两个字符串的长度。
2. 处理特殊情况:如果任一字符串长度为0,返回-1.
3. 创建二维数组dp,并初始化为0.
4. 初始化max_len=0,start_pos=-1.
5. 遍历i从1到len1:
遍历j从1到 len2:
如果s1[i-1] == s2[j-1]:
dp[i][j] = dp[i-1][j-1] +1
if dp[i][j] > max_len:
max_len = dp[i][j]
start_pos = i - max_len // 在s1中的结束位置是i-1,所以起始位置是i - max_len
else:
dp[i][j] =0
6. 释放动态分配的二维数组。
7. 如果max_len >0,返回start_pos +1(转换为1-based),否则返回-1.
需要注意的是,在C语言中,数组的索引是从0开始的,所以i和j的循环处理要正确。
例如,假设s1是"abc",i的范围是1到3:
i=1 → s1[0] = 'a'
i=3 → s1[2] = 'c'
所以,当i=3时,s1[i-1]是正确访问的。
现在,测试一下例子:
s1 = "fu#stuentgh",其各个字符的索引(0-based)如下:
0: f
1: u
2: #
3: s
4: t
5: u
6: e
7: n
8: t
9: g
10: h
s2 = "student"的索引:
0: s
1: t
2: u
3: d
4: e
5: n
6: t
在动态规划过程中,当i=4(s1的索引3,字符's'),j=1(s2的索引0,字符's')时,相等,所以dp[4][1] = 1。此时max_len变为1,start_pos =4-1=3 → 0-based起始位置3,即返回4(1-based)。
之后,i=5(s1[4]='t'),j=2(s2[1]='t'),相等。此时dp[5][2] = dp[4][1]+1=2。max_len变为2,start_pos=5-2=3 →起始位置3.
i=6(s1[5]='u'),j=3(s2[2]='u'),相等。dp[6][3] = dp[5][2]+1=3。max_len变为3,start_pos=6-3=3 →起始位置3.
i=7(s1[6]='e'),j=4(s2[3]='d'):不相等,dp[7][4]=0.
此时,max_len保持3,start_pos=3.
后面可能还有其他的匹配,但长度可能更短。例如,s1中的e在索引6,s2中的e在索引4。这时候可能需要后续的匹配,但当前的最大长度是3.
因此,最终start_pos是3(0-based),返回3+1=4,符合例子。
所以,这个算法是正确的。
现在,考虑如何用C语言实现这个函数,并且使用指针。题目中要求使用函数和指针,所以函数参数是两个字符串指针,返回int。
此外,在C语言中,动态分配二维数组可能会有内存泄漏的问题,需要记得释放分配的内存。
所以,代码的大致结构:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int find_common_segment(char *s1, char *s2) {
int len1 = strlen(s1);
int len2 = strlen(s2);
if (len1 ==0 || len2 ==0) {
return -1;
}
int max_len = 0;
int start_pos = -1;
// 创建dp数组
int **dp = (int **)malloc((len1 +1) * sizeof(int *));
for (int i=0; i <= len1; i++) {
dp[i] = (int *)calloc(len2 +1, sizeof(int)); // 初始化为0
}
for (int i=1; i <= len1; i++) {
for (int j=1; j <= len2; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] +1;
if (dp[i][j] > max_len) {
max_len = dp[i][j];
start_pos = i - max_len; // 0-based起始位置
}
} else {
dp[i][j] = 0;
}
}
}
// 释放内存
for (int i=0; i <= len1; i++) {
free(dp[i]);
}
free(dp);
if (max_len >0) {
return start_pos +1; // 转为1-based
} else {
return -1;
}
}
// 测试例子
int main() {
char s1[] = "fu#stuentgh";
char s2[] = "student";
int result = find_common_segment(s1, s2);
printf("返回值:%d\n", result); // 应该输出4
return 0;
}
但是,这个代码存在一个问题:当有多个相同长度的最长公共子串时,会记录最后一个出现的,而不是第一个。例如,假设第一个出现的最长子串在某个位置,后面又出现同样长度的子串,那么start_pos会被更新为后面的位置。这与题目中的例子是否要求第一个出现的相冲突?
例如,假设s1是“abcxyzabc”,s2是“xyzabc”,那么最长公共子串是“abc”(长度3)出现在后面,或者“xyz”出现在前面。此时,动态规划的方法会找到后面出现的“abc”作为最长子串,还是前面的“xyz”?
这可能根据dp的遍历顺序而定。例如,当遍历到后面的i和j时,如果发现更长的子串,或者同样长度的子串,max_len会被更新吗?
比如,假设前面有一个最长子串长度为3,后面又有一个同样长度的子串,此时在代码中,因为dp[i][j]等于max_len,所以不会更新start_pos,所以start_pos还是前面的那个起始位置?
不,在代码中,当dp[i][j]等于max_len的时候,不会进入if条件,所以不会更新。例如,当前max_len是3,当遇到另一个dp[i][j]等于3的时候,条件dp[i][j] > max_len不满足,所以不会更新start_pos。所以start_pos仍然是第一个出现的最长子串的起始位置。
哦,不,原代码中的条件是:
if (dp[i][j] > max_len) {
max_len = dp[i][j];
start_pos = i - max_len;
}
所以,只有当当前dp值大于max_len时,才会更新。当等于的时候,不会处理。所以,当最长子串的长度是3,之后出现的同样长度的子串不会被处理。因此,start_pos记录的是第一个出现的最长子串的起始位置。
那是否正确?
例如,s1是“ababc”,s2是“abcab”. 最长公共子串是“ab”和“abc”(如果存在的话)。或者假设有一个更长的例子。比如,s1是“abcxabc”,s2是“abcxabc”,那么最长公共子串是整个字符串,此时start_pos是0-based的0,返回1。正确。
假设,s1是“xyzabc”,s2是“abcxyz”,那么最长公共子串是“abc”或者“xyz”。在比较时,哪边会被先找到?
例如,在i=1(s1[0]是x),j=4(s2[3]是x)的时候,当比较x和x时,可能开始匹配。如果后续的字符不同,这可能形成长度为1的子串。而最长公共子串可能是“xyz”长度3或者“abc”长度3。假设在遍历时,先找到“xyz”的位置,后面又找到“abc”的位置,此时max_len是3,但后面出现的同样长度不会改变start_pos。所以会返回第一个出现的位置?
不,不一定。例如,假设s1是“xyzabc”,s2是“abcxyz”:
当i=1(x)时,j=4(x):相等,dp[1][4]=1。max_len=1,start_pos=0.
当i=2(y),j=5(y):相等,dp[2][5] = dp[1][4] +1=2. max_len=2,start_pos=0.
i=3(z),j=6(z):dp[3][6]=3. max_len=3,start_pos=0.
然后,当i=4(a),j=1(a):相等,dp[4][1]=1.此时max_len仍为3.
当i=5(b),j=2(b):相等,dp[5][2]=2.
i=6(c),j=3(c):dp[6][3]=3.此时max_len等于3,所以不会更新start_pos。此时i=6 -3=3。start_pos是3,而之前的start_pos是0。此时,由于dp[i][j]等于max_len,所以不会更新。所以最终返回的是start_pos=0,转换为1-based是1。
所以,动态规划的方法会记录第一个出现的最长子串的起始位置。
所以,代码中的逻辑是正确的。
因此,这段代码应该能够正确处理题目中的例子,并且返回正确的起始位置。
接下来,测试代码中的例子。在main函数中,s1是“fu#stuentgh”,s2是“student”,运行后的返回值应该是4。运行代码,查看结果是否正确。
另外,需要处理其他情况,例如没有公共子串的情况,返回-1。
例如,s1是“abcd”,s2是“efg”,函数返回-1.
综上,这个代码应该满足题目要求,使用函数和指针(通过参数传递字符串指针),并且通过动态规划找到最长的公共子串的起始位置。</think>以下是解决该问题的分步说明和代码实现:
### 思路分析
1. **问题理解**:在两个字符串中查找最长的公共连续子串,并返回该子串在第一个字符串中的起始位置(1-based)。若不存在公共子串,返回-1。
2. **动态规划方法**:
- 定义二维数组 `dp[i][j]` 表示以第一个字符串的第 `i` 个字符和第二个字符串的第 `j` 个字符结尾的最长公共子串长度。
- 当字符匹配时,递推公式为 `dp[i][j] = dp[i-1][j-1] + 1`。
- 记录最长公共子串的长度及其起始位置。
### 代码实现
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int find_common_segment(char *s1, char *s2) {
int len1 = strlen(s1);
int len2 = strlen(s2);
if (len1 == 0 || len2 == 0) return -1;
int max_len = 0;
int start_pos = -1;
// 动态分配二维数组并初始化
int **dp = (int **)malloc((len1 + 1) * sizeof(int *));
for (int i = 0; i <= len1; i++) {
dp[i] = (int *)calloc(len2 + 1, sizeof(int));
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > max_len) {
max_len = dp[i][j];
start_pos = i - max_len; // 计算起始位置(0-based)
}
} else {
dp[i][j] = 0;
}
}
}
// 释放内存
for (int i = 0; i <= len1; i++) {
free(dp[i]);
}
free(dp);
return (max_len > 0) ? (start_pos + 1) : -1; // 转为1-based
}
int main() {
char s1[] = "fu#stuentgh";
char s2[] = "student";
int result = find_common_segment(s1, s2);
printf("起始位置:%d\n", result); // 应输出4
return 0;
}
```
### 关键步骤说明
1. **初始化二维数组**:使用动态内存分配创建二维数组 `dp`,并初始化为0。
2. **填充动态规划表**:遍历两个字符串的所有字符组合,根据字符是否匹配更新 `dp` 数组。
3. **记录最长子串**:在遍历过程中,实时更新最长公共子串的长度及其起始位置。
4. **结果处理**:根据最长子串长度判断返回值,若存在则返回1-based的起始位置,否则返回-1。
### 示例验证
- **输入**:`s1 = "fu#stuentgh"` 和 `s2 = "student"`
- **处理过程**:
- 最长公共子串为 `"stu"`,长度3。
- 在 `s1` 中的起始位置为3(0-based),转换为1-based即4。
- **输出**:4
此方法通过动态规划高效解决了问题,时间复杂度为 $O(n \cdot m)$,空间复杂度为 $O(n \cdot m)$,适用于一般规模的字符串处理。
阅读全文
相关推荐


















