data从0开始存根据KMP算法进行了调整,歪打正着做对了
回头进行分析时遇到了麻烦
存储地址/实际地址 颠来倒去 实在不明白
T1型·数组·固定长度(a[0]起存/半成品/next)
已停止对该代码段的维护
#include <stdio.h>
#include <string.h>
#include <iostream>
typedef struct skr
{
char data[233]; //定义可容纳233个字符的空间
int l; //标记当前实际串长
};
// ABABABBBAAABABAAAABABAAABABAAABABAAABABAA
// ABABAAABABAA
// 011234223456 重叠区T18 (back里存 存储地址,+1后得到实际 第几个元素)
// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
// aaaaaab
//《功能模块·10种》
void init(skr &a)
{
memset(a.data, 0, sizeof(a.data));
a.l = 0;
}
void create(skr &s, char cstr[])
{ //《创建》
int i;
for (i = 0; cstr[i] != '\0'; i++)
s.data[i] = cstr[i];
s.l = i;
}
void copy(skr &s, skr t)
{ //《复制》
int i;
for (i = 0; i < t.l; i++)
s.data[i] = t.data[i];
s.l = t.l;
}
bool equal(skr s, skr t)
{ //《相同?》
bool f = true;
int i;
if (s.l != t.l) //长度不相等时返回0
f = false;
else
for (i = 0; i < s.l; i++)
if (s.data[i] != t.data[i])
{ //有一个对应字符不相同时返回0
f = false;
break;
}
return f;
}
int len(skr s)
{ //《长度》
return s.l;
}
skr contact(skr s, skr t)
{ //《合并·双串》
skr str;
int i;
str.l = s.l + t.l;
for (i = 0; i < s.l; i++) //将s.data[0..s.l-1]复制到str
str.data[i] = s.data[i];
for (i = 0; i < t.l; i++) //将t.data[0..t.l-1]复制到str
str.data[s.l + i] = t.data[i];
return str;
}
skr take_out(skr s, int i, int j)
{ //《提取·子串·i-->j》
skr str;
int k;
str.l = 0;
if (i <= 0 || i > s.l || j < 0 || i + j - 1 > s.l)
return str; //参数不正确时返回空串
for (k = i - 1; k < i + j - 1; k++) //将s.data[i..i+j]复制到str
str.data[k - i + 1] = s.data[k];
str.l = j;
return str;
}
skr insert(skr s1, int i, skr s2)
{ //《插入·i位置·插入·s2》
int j;
skr str;
str.l = 0;
if (i <= 0 || i > s1.l + 1) //参数不正确时返回空串
return str;
for (j = 0; j < i - 1; j++) //将s1.data[0..i-2]复制到str
str.data[j] = s1.data[j];
for (j = 0; j < s2.l; j++) //将s2.data[0..s2.l-1]复制到str
str.data[i + j - 1] = s2.data[j];
for (j = i - 1; j < s1.l; j++) //将s1.data[i-1..s1.l-1]复制到str
str.data[s2.l + j] = s1.data[j];
str.l = s1.l + s2.l;
return str;
}
skr del(skr s, int i, int j)
{ //《删除·i起删除j个》
int k;
skr str;
str.l = 0;
if (i <= 0 || i > s.l || i + j > s.l + 1) //参数不正确时返回空串
return str;
for (k = 0; k < i - 1; k++) //将s.data[0..i-2]复制到str
str.data[k] = s.data[k];
for (k = i + j - 1; k < s.l; k++) //将s.data[i+j-1..s.l-1]复制到str
str.data[k - j] = s.data[k];
str.l = s.l - j;
return str;
}
skr replace(skr s, int i, int j, skr t)
{ //《替换·s中i开始j个·换成t》
int k;
skr str;
str.l = 0;
if (i <= 0 || i > s.l || i + j - 1 > s.l) //参数不正确时返回空串
return str;
for (k = 0; k < i - 1; k++) //将s.data[0..i-2]复制到str
str.data[k] = s.data[k];
for (k = 0; k < t.l; k++) //将t.data[0..t.l-1]复制到str
str.data[i + k - 1] = t.data[k];
for (k = i + j - 1; k < s.l; k++) //将s.data[i+j-1..s.l-1]复制到str
str.data[t.l + k - j] = s.data[k];
str.l = s.l - j + t.l;
return str;
}
void print(skr s)
{ //《输出·串》
int i;
if (s.l > 0)
{
printf("%s", s.data);
}
}
void menu(skr s1, skr s2)
{ //《菜单》
system("cls");
printf("S1: ");
print(s1);
printf(" 长度:%d\n", len(s1));
printf("S2: ");
print(s2);
printf(" 长度:%d\n", len(s2));
printf("1-创建s1\t2-创建s2\t3-插入\t4-删除\n");
printf("5-替换\t\r6-提取\t\t7-连接\t\t8-清空\t9-查找\n");
printf("请输入您的选择:");
}
bool clear(skr &s)
{ //《清空》
s = del(s, 1, s.l);
s.l = 0;
}
int search(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 复杂度O(n*m)
int i = t - 1, j = 0;
printf("\n采用暴力算法!O(n*m)\n");
// printf("%d %d %d %d\n",s1.l,s2.l,i,j);
while (i < s1.l && j < s2.l)
{ //主串读取完成·已经发现了子串·则跳出
if (s1.data[i] == s2.data[j])
{
i++;
j++;
// printf("i=%d j=%d 相同! j=%d\n",i-1,j-1,j);
}
else
{
// printf("i=%d j=%d 不同!",i,j);
i = i - j + 1;
j = 0;
// printf(" i=%d,j=%d\n",i,j);
}
} // printf("%d %d %d\n",i,s2.l,i-s2.l);
if (j == s2.l)
return i - s2.l + 1; //例如asdqwe123 找qwe,读取到e是i=5,+1后跳出=6,这时候恰好=实际地址(末尾)
else
return 0; //此时-3后=3,指向d就不对,因为只需要往右移动2格即可
}
void get_next(skr s2, int t[])
{ //《KMP辅助!由子串生成back数组》
int x = 1, y = 0, i;
while (x <= s2.l)
{
// printf("x=%d\ty=%d\n", x, y);
/*for (i = 1; i <= x; i++)
printf(" ");
printf("X\n");
printf("%s\n", s2);
for (i = 1; i <= y; i++)
printf(" ");
printf("Y\n");*/
if (y == 0 || s2.data[x] == s2.data[y])
{ //这里的x y运用是都是存储地址
t[++x] = ++y; //[]优先级>++(前置也没用,先算再各种++),等价于t[1]=y=0;x++;y++;
/*if (s2.data[x] == s2.data[y])
printf(" 相同");
else
printf(" 启封");
printf("的元素!x、y各+1。t[%d]=%d\n", x - 1, t[x - 1]);*/
}
else
{
// printf(" 不同的元素!y由%d退回到%d\n", y, t[y]);
y = t[y];
}
// printf("/-----------------------------------------/\n");
}
}
int KMP(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 KMP算法 复杂度O(n+m)
printf("\n启用KMP算法!·O(n+m)\n");
int back[233] = {}, x, y, z;
get_next(s2, back);
// t[x]=y; 实际位置x发现异常,则退回到实际位置y(子串指针)
printf("NEXT情况报备:");
for (x = 1; x <= s2.l; x++)
printf("%d ", back[x]);
printf("\n\n");
x = t - 1;
y = 0;
while (x < s1.l && y < s2.l)
{
// printf("x=%d y=%d", x, y);
if (y == 0 || s1.data[x] == s2.data[y])
{
x++;
y++;
/*if (s2.data[x] == s2.data[y])
printf("相同");
else
printf("启封");
printf("的元素!x、y各+1 .\n");*/
}
else
{
// printf("不同的元素!将y从%d回溯到%d\n", y, back[y]);
y = back[y];
}
}
if (y == s2.l)
return x - s2.l + 1;
else
return 0;
} //优点在于不用回溯i指针,而是利用 部分匹配+滑动的机制
int main()
{
skr s1, s2, s3, s4;
init(s1);
init(s2);
init(s3);
init(s4);
int x, y, z;
char a[233], t;
while (1)
{
menu(s1, s2);
scanf("%d", &x);
printf("\n");
switch (x)
{
case 1:
{ //《创建s1》
scanf("%c", &t); //挡住回车键
gets(a);
init(s1);
create(s1, a);
break;
}
case 2:
{ //《创建s2》
scanf("%c", &t);
gets(a);
init(s2);
create(s2, a);
break;
}
case 3:
{ //《插入·s1s2互插》
printf("s1,s2,谁是攻?");
scanf("%d", &x);
if (x == 1)
{
printf("向s2第x个字符插入串s1,输入x:");
scanf("%d", &x);
s2 = insert(s2, x, s1);
}
else
{
printf("向s1第x个字符插入串s2,输入x:");
scanf("%d", &x);
s1 = insert(s1, x, s2);
}
break;
}
case 4:
{ //《删除·可选》
printf("对谁进行操作:");
scanf("%d", &x);
if (x == 1)
{
printf("对S%d操作!第x起删除y个:", x);
scanf("%d%d", &x, &y);
s1 = del(s1, x, y);
}
else
{
printf("对S%d操作!第x起删除y个:", x);
scanf("%d%d", &x, &y);
s2 = del(s2, x, y);
}
break;
}
case 5:
{ //《替换》
printf("谁被替换插入:");
scanf("%d", &x);
if (x == 1)
{
printf("输入替换的字符段:");
scanf("%d%d", &x, &y);
s1 = replace(s1, x, y, s2);
}
else
{
printf("输入替换的字符段:");
scanf("%d%d", &x, &y);
s2 = replace(s2, x, y, s1);
}
break;
}
case 6:
{ //《提取》
printf("从哪个串开始提取?从x起共y个?");
scanf("%d%d%d", &z, &x, &y);
if (z == 1)
s3 = take_out(s1, x, y);
else
s3 = take_out(s2, x, y);
printf("捕获子串! ");
print(s3);
printf("\n");
break;
}
case 7:
{ //《连接》
s3 = contact(s1, s2);
printf("完成链接! ");
print(s3);
printf("\n");
break;
}
case 8:
{ //《清空》
printf("清空谁:");
scanf("%d", &x);
if (x == 1)
clear(s1);
if (x == 2)
clear(s2);
break;
}
case 9:
{ //《查找·子串》
printf("谁是主串?从第几个开始查找?是否采用KMP算法?");
scanf("%d%d%d", &x, &y, &z);
if (x == 1 && z == 0)
z = search(s1, s2, y);
else if (x == 2 && z == 0)
z = search(s2, s1, y);
else if (x == 1 && z == 1)
z = KMP(s1, s2, y);
else if (x == 2 && z == 1)
z = KMP(s2, s1, y);
if (z != 0)
printf("发现子串!位于%d\n", z);
break;
}
}
printf("\n");
system("pause");
}
return 0;
}
// 2021/10/07 寂之锋·第七军团·科研攻坚小组(任务:PTA试题全覆盖·数构基础块全覆盖)
T2型·数组·固定长度(a[1]起存/成品/next/nextval)
#include <stdio.h> // 2021/10/07 寂之锋·第七军团·科研攻坚小组(任务:PTA试题全覆盖·数构基础块全覆盖)
#include <string.h> //测试数据
#include <iostream> //ABABABBBAAABABAAAABABAAABABAAABABAAABABAA
#define max 2745 // ABABAAABABAA
typedef struct skr
{
char data[max]; //定义可容纳max个字符的空间
};
void get_nextval(skr T, int n[])
{ //《get_nextval》
int i = 1, j = 0;
n[1] = 0;
while (i < T.data[0])
{
if (j == 0 || T.data[i] == T.data[j])
{
++i, ++j;
if (T.data[i] != T.data[j])
n[i] = j;
else
n[i] = n[j];
}
else
j = n[j];
}
for (i = 1; i <= T.data[0]; i++)
printf("%d ", n[i]);
}
void create(skr &s, char cstr[])
{ //《创建》
int i;
for (i = 0; cstr[i] != '\0'; i++)
s.data[i + 1] = cstr[i]; //从1开始存,0存总长度
s.data[0] = i;
}
bool equal(skr s, skr t)
{ //《相同?》
bool f = true;
int i;
if (s.data[0] != t.data[0]) //长度不相等时返回0
f = false;
else
for (i = 1; i <= s.data[0]; i++)
if (s.data[i] != t.data[i])
{ //有一个对应字符不相同时返回0
f = false;
break;
}
return f;
}
int len(skr s)
{ //《长度》
return s.data[0];
}
skr contact(skr s, skr t)
{ //《合并·双串》
skr str;
int i;
str.data[0] = s.data[0] + t.data[0];
for (i = 1; i <= s.data[0]; i++) //将s.data[0..s.data[0]-1]复制到str
str.data[i] = s.data[i];
for (i = 1; i <= t.data[0]; i++) //将t.data[0..t.data[0]-1]复制到str
str.data[s.data[0] + i] = t.data[i];
return str;
}
skr take_out(skr s, int i, int j)
{ //《提取·子串·i后 j个》
skr str;
int k;
str.data[0] = 0;
if (i <= 0 || i > s.data[0] || j < 0 || i + j > s.data[0] + 1)
return str; //参数不正确时返回空串
for (k = i; k <= i + j; k++) //将s.data[i..i+j]复制到str
str.data[k - i + 1] = s.data[k]; //从1开始存,内容存k=i开始
str.data[0] = j;
return str;
}
skr insert(skr s1, int i, skr s2)
{ //《插入·i位置·插入·s2》
int j;
skr str;
str.data[0] = 0;
if (i <= 0 || i > s1.data[0] + 1) //参数不正确时返回空串
return str;
for (j = 1; j <= i - 1; j++) //前i-1个 (共i-1个)
str.data[j] = s1.data[j];
for (j = 1; j <= s2.data[0]; j++) //新的串 从i开始 (共s2个)
str.data[i + j - 1] = s2.data[j]; //(空位:s2+i是空的)
for (j = i; j <= s1.data[0]; j++) //后半段(原来的i不可以丢)
str.data[s2.data[0] + j] = s1.data[j];
str.data[0] = s1.data[0] + s2.data[0];
return str;
}
skr del(skr s, int i, int j)
{ //《删除·i起删除j个》
int k;
skr str;
str.data[0] = 0;
if (i <= 0 || i > s.data[0] || i + j > s.data[0] + 1) //参数不正确时返回空串
return str;
for (k = 1; k <= i - 1; k++) // i-1前给str
str.data[k] = s.data[k];
for (k = i + j; k <= s.data[0]; k++) // i+j开始接上去
str.data[k - j] = s.data[k];
str.data[0] = s.data[0] - j;
return str;
}
skr replace(skr s, int i, int j, skr t)
{ //《替换·s中i开始j个·换成t》
int k, S1 = s.data[0], S2 = t.data[0];
skr T;
if (i <= 0 || i > S1 || i + j > S1 + 1) //参数不正确时返回空串 例如6个 从5起替换2个,换掉5和6,是可以的,但是5+2=7=6+1>6,这是可以的;但是再+1不行
return T;
for (k = 1; k <= i - 1; k++) // s的前i-1进去 (总长:i-1)(下个空点:i)
T.data[k] = s.data[k];
for (k = 1; k <= S2; k++) //替换区进去 (总长:i-1+s2)(下个空点:i+s2)
T.data[i - 1 + k] = t.data[k];
for (k = i + j; k <= S1; k++) //后段接入
T.data[S2 + k - j] = s.data[k];
T.data[0] = S1 - j + S2;
return T;
}
void print(skr s)
{ //《输出·串》
int i;
if (s.data[0] > 0)
for (i = 1; i <= s.data[0]; i++)
printf("%c", s.data[i]);
}
void menu(skr s1, skr s2)
{ //《菜单》
system("cls");
printf("S1: ");
print(s1);
printf(" 长度:%d\n", len(s1));
printf("S2: ");
print(s2);
printf(" 长度:%d\n", len(s2));
printf("1-创建s1\t2-创建s2\t3-插入\t4-删除\n");
printf("5-替换\t\r6-提取\t\t7-连接\t\t8-清空\t9-查找\n10-get_nextval\n");
printf("请输入您的选择:");
}
bool clear(skr &s)
{ //《清空》
s = del(s, 1, s.data[0]);
s.data[0] = 0;
}
int search(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 复杂度O(n*m)
int i = t, j = 1;
printf("\n采用暴力算法!O(n*m)\n");
// printf("%d %d %d %d\n",s1.data[0],s2.data[0],i,j);
while (i <= s1.data[0] && j <= s2.data[0])
{ //主串读取完成·已经发现了子串·则跳出
if (s1.data[i] == s2.data[j])
{
i++;
j++;
// printf("i=%d j=%d 相同! j=%d\n",i-1,j-1,j);
}
else
{
// printf("i=%d j=%d 不同!",i,j);
i = i - j + 2;
j = 1;
// printf(" i=%d,j=%d\n",i,j);
}
// printf("%d %d %d\n",i,s2.data[0],i-s2.data[0]);
}
if (j == s2.data[0] + 1)
return i - s2.data[0];
else
return 0;
}
bool map(int x, int y, skr s2, int t[])
{ //《反馈·指针情况》
printf("-----------------------------------------\n");
printf("x=%d\ty=%d\n", x, y);
int i;
for (i = 1; i <= x; i++)
printf(" ");
printf("X\n ");
print(s2);
printf("\n");
for (i = 1; i <= y; i++)
printf(" ");
printf("Y\n ");
for (i = 1; i <= s2.data[0]; i++)
printf("%d", t[i]);
printf("\n");
return true;
}
bool map2(int x, int y, skr s1, skr s2, int t[])
{ //《反馈·指针情况》
printf("\n");
int i; // 1主串 2子串
for (i = 1; i <= x; i++)
printf(" ");
printf("X\n ");
print(s1);
printf("\n ");
print(s2);
printf("\n");
for (i = 1; i <= y; i++)
printf(" ");
printf("Y\n ");
for (i = 1; i <= s2.data[0]; i++)
printf("%d", t[i]);
printf("\n\n");
return true;
}
void get_next(skr s2, int t[])
{ //《KMP辅助!由子串生成back数组》
int x = 1, y = 0;
t[1] = 0;
while (x < s2.data[0])
{
// map(x, y, s2, t);
if (y == 0 || s2.data[x] == s2.data[y])
{ /*
if (s2.data[x] == s2.data[y])
printf(" 相同");
else
printf(" 虚无");*/
t[++x] = ++y;
// printf("的元素!x、y各+1。t[%d]=%d\n", x, y);
}
else
{
// printf(" 不同的元素!y由%d退回到%d\n", y, t[y]);
y = t[y];
} /*
if (x == s2.data[0])
printf("-----------------------------------------\n");*/
}
}
int KMP(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 KMP算法 复杂度O(n+m)
printf("\n启用KMP算法!·O(n+m)\n");
int back[max] = {}, x, y, z, k = 0;
get_next(s2, back);
printf("NEXT情况报备:");
for (x = 1; x <= s2.data[0]; x++)
printf("%d ", back[x]);
printf("\n");
x = t;
y = 1; //从t开始找,包括t x在右边,是主串指针,y是子串指针
while (x <= s1.data[0] && y <= s2.data[0])
{
// printf("%d:\t", ++k);
// printf("x=%d y=%d", x, y);
// map2(x, y, s1, s2, back);
if (y == 0 || s1.data[x] == s2.data[y])
{ /*
if (s1.data[x] == s2.data[y])
printf("相同");
else
printf("启封");*/
x++;
y++;
// printf("的元素!x、y各+1 .\n");
}
else
{
// printf("不同的元素!将y从%d回溯到%d\n", y, back[y]);
y = back[y];
}
// printf("--------------------------------------------------\n");
}
//如果追踪成功,那么y指针,实际数值 = 子串总长度+1
if (y == s2.data[0] + 1)
{
//printf("x=%d y=%d y溢出!说明子串遍历完成。\n子串长度:%d。\n", x, y, s2.data[0]);
return x - s2.data[0];
}
else
return 0; //总长8,结束x=9,子串3,9-3=6,恰好=相同子串打头位置
} //优点在于不用回溯i指针,而是利用 部分匹配+滑动的机制
int main()
{
skr s1, s2, s3, s4;
s1.data[0] = 0;
s2.data[0] = 0;
s3.data[0] = 0;
s4.data[0] = 0;
int x, y, z, k[max];
char a[max], t;
while (1)
{
menu(s1, s2);
scanf("%d", &x);
printf("\n");
switch (x)
{
case 1:
{ //《创建s1》
printf("输入S1字符串:");
scanf("%c", &t); //挡住回车键
gets(a);
create(s1, a);
break;
}
case 2:
{ //《创建s2》
printf("输入S2字符串:");
scanf("%c", &t);
gets(a);
create(s2, a);
break;
}
case 3:
{ //《插入》
printf("谁被插入?互插 或 新建?插入位置?");
scanf("%d%d%d", &x, &y, &z);
if (x == 1 && y == 1)
s1 = insert(s1, z, s2);
if (x == 2 && y == 1)
s2 = insert(s2, z, s1);
if (y == 2)
{
printf("输入字符串s3:");
scanf("%c", &t); //挡住回车键
gets(a);
create(s3, a);
if (x == 1)
s1 = insert(s1, z, s3);
if (x == 2)
s2 = insert(s2, z, s3);
}
break;
}
case 4:
{ //《删除·可选》
printf("对z进行操作,第x起删除y个:");
scanf("%d%d%d", &z, &x, &y);
if (z == 1 && s1.data[0] != 0)
s1 = del(s1, x, y);
if (z == 2 && s2.data[0] != 0)
s2 = del(s2, x, y);
break;
}
case 5:
{ //《替换》
printf("z被替换,替换的字符段x起共y个(包括x):");
scanf("%d%d%d", &z, &x, &y);
if (x == 1)
s1 = replace(s1, x, y, s2);
if (x == 2)
s2 = replace(s2, x, y, s1);
break;
}
case 6:
{ //《提取》
printf("从哪个串开始提取?从x起共y个?");
scanf("%d%d%d", &z, &x, &y);
if (z == 1)
s3 = take_out(s1, x, y);
else if (z == 2)
s3 = take_out(s2, x, y);
else
break;
if (s3.data[0] == 0)
break;
printf("捕获子串! ");
print(s3);
printf("\n");
break;
}
case 7:
{ //《连接》
printf("是s1后接s2?");
scanf("%d", &x);
if (x == 1)
s3 = contact(s1, s2);
if (x == 0)
s3 = contact(s2, s1);
printf("完成链接! ");
print(s3);
printf("\n");
break;
}
case 8:
{ //《清空》
printf("清空谁:");
scanf("%d", &x);
if (x == 1)
clear(s1);
if (x == 2)
clear(s2);
break;
}
case 9:
{ //《查找·子串》
printf("谁是主串?从第几个开始查找?是否采用KMP算法?");
scanf("%d%d%d", &x, &y, &z);
if (x == 1 && z == 0)
z = search(s1, s2, y);
else if (x == 2 && z == 0)
z = search(s2, s1, y);
else if (x == 1 && z == 1)
z = KMP(s1, s2, y);
else if (x == 2 && z == 1)
z = KMP(s2, s1, y);
if (z != 0)
printf("发现子串!位于%d\n", z);
break;
}
case 10:
{ //《get_nextval》
scanf("%c", &t); //挡住回车键
gets(a);
create(s4, a);
get_nextval(s4, k);
break;
}
}
printf("\n");
system("pause");
}
return 0;
}
明明一个char a[233]就能搞定了,为什么书上非要搞个typedef?对我这种菜鸟很不友好
这个代码还能改进成非typedef的,但是由于我不会在函数中引用char数组,所以只好先这样
关于KMP的next数组生成的算法
将子串从头开始,拆2个,拆3个,拆4个,一直到拆n个,称为“拆解子串”
X:尾部指针,指向 拆解子串尾部
Y:头部指针,记录当前 最大公共前后缀的长度
next[x+1]:如果x+1位置不对,他要跳到哪个位置去?
T1如果(头部指针指向虚无/存在相同元素)
t[++x]=++y; 先都+1,再赋值
1.指向虚无即不存在相同的元素,那么结论出来了
x+1位置不对,从头(1)开始找吧
2.存在相同,说明x+1不同时,跳到 Y+1
(即可保证,前边Y个元素 和 异动前的Y个元素 相同)
对于x长度子串的分析,意义是对于x+1的位置
如果x+1位置不对,他要跳到哪个位置去?
答案:当前最长公共前后缀长度+1 叫做 Y+1
所以next[x+1]=y+1(翻译:x+1位置不对,跳到Y+1)
T2否则,对y进行回溯
Y移到 t[y]
让前段的t[y]-1个元素和移动前是相同的
而赋值后的y,也就是之前的t[y]
头部指针,当前点,需要再次验证,是否和尾部相同
如果是(第二轮if),说明 当前的Y就是 当前的最大公共子序列长度
(Y指向5,那么 包括Y以及前面的点 都和 包括尾指针X起5个点 相同)
如果不是(第二轮else),说明现在Y点以及之前的点不对,还要继续回溯
利用next[x]回溯,目的是:让前面部分尽可能保持一致前提下
加快回跳速度,绕开一些不必要的比对
而不是一步一步往回退