题目描述
假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,则可共享相同的后缀空间。设str1和str2分别指向两个单词所在单链表的头结点,请实现一个时间上尽可能高效的算法,找出由str1和str2所指的两个链表共同后缀的起始位置的结点,输出该结点对应的字符。
输入
多组数据,每组数据有三行,第一行为链表str1和str2的长度n和m,第二行为链表str1的n个元素,第三行为链表str2的m个元素(元素之间用空格分隔)。n=0且m=0时输入结束。
7 5
l o a d i n g
b e i n g
7 9
f l u e n c y
f r e q u e n c y
0 0
输出
对于每组数据输出一行,为共同后缀的起始位置结点对应的字符。
i
u
代码实现:
#include <bits/stdc++.h>
using namespace std;
typedef struct LNode
{
char data;
struct LNode *next;
}LNode,*LinkNode;
void Initlist(LinkNode &L)//初始化链表
{
L=new LNode;
L->next=NULL;
}
void Input(LinkNode &L,int n)//输入数据
{
LinkNode p,r;
r=L;
char num;
while(n--)
{
cin>>num;
p=new LNode;
p->data=num;
r->next=p;
r=p;
}
r->next=NULL;
}
void Createlist(LinkNode &str1,LinkNode &str2,int n,int m)//每次创建两个链表,所以要输入两个链表的数据
{
Input(str1,n);
Input(str2,m);
}
void chazhao(LinkNode str1,LinkNode str2,int n,int m)//查找共同后缀的起始点
{
LinkNode p,q;
if(n>m)
{
p=str1->next;
q=str2->next;
}
else
{
p=str2->next;
q=str1->next;
}
/*if和else是使p一直指向最长的链表,只是为了方便遍历,不让自己逻辑混乱*/
int cha,count=0;
cha=n-m;
if(cha<0) cha=-cha;
while(count<cha)
{
p=p->next;
count++;
}
/*使p向后移动n次(n是q指向的链表的长度),因为多余的那几个都是再前面,
不会影响我们要求的后缀,只有在下面第一个while循环时,让p和q继续遍历的次数相等,才能一一对应*/
char s;
int flag;
LinkNode p1,q1;
p1=p;
q1=q;
/*p1和q1,是为了p->data和q->data出现相等时,继续判断后面的值是否相等*/
while(p&&q)
{
flag=0;
if(p->data!=q->data)
{
p=p->next;
q=q->next;
p1=p1->next;
q1=q1->next;
continue;
}
else
{
s=p->data;
flag=1;//出现相等的点,先让flag=1;
p=p->next;
q=q->next;
while(p1&&q1)
{
if(p1->data!=q1->data)
{
flag=0;//后面的值不相等,再让flag=0;
break;
}
p1=p1->next;
q1=q1->next;
}
if(flag) break;//如果后面的值,全部都相等(flag没有改变),跳出循环
}
}
if(flag)
cout<<s<<endl;//输出s
}
int main()
{
int n,m;
cin>>n>>m;
while(n!=0&&m!=0)
{
LinkNode str1,str2;
Initlist(str1);
Initlist(str2);
Createlist(str1,str2,n,m);
chazhao(str1,str2,n,m);
cin>>n>>m;
}
return 0;
}
函数查找chazhao部分的解释:
用while循环,遍历p和q,如果对应值不相等,就跳过此次循环,如果相等,定义一个char类型s,用s存储此时相等的值(任意一个即可,这里存的是p->data),让flag=1,再开一个循环,判断后面的值(直到结束)是否相等,如果不相等,让flag=0,break,跳出循环,如果相等,输出刚刚标记的s.