题目要求:输入两个字符串,输出它们的最长公共子串,包括长度。
设计一个类String,包括一个len(字符串长度)和字符串指针s。
这是一个简单思路:
讲解一下:
对于两个输入的字符串,在其成员函数知道其长度后,便可以开始查找出相同字符串:
定义:
可以定义一个 int类型的k,目的是当遍历到两字符串中相同字符时继续往下遍历时可以用k来使两字符同时往后读取,再往后读取只需将k进行 ++处理即可;
然后还需定义length记录最大相同字串的长度,index记录其索引位置;
再定义一个length1来记录当前相同字符串的长度,若>length 就取代。
思路分析:
int index=-1,length=0,length1=0,i=0,j,k;
while (i<str1.len) //插入循环进行遍历处理
{ j=0; //每次下面数组遍历玩之后第一个字符串数组重新开始遍历
while(j<str2.len) //在不超过其长度的条件下遍历,超过就没有丝毫意义了
{
if (str1.s[i]==str2.s[j]) //当两者字符相同时进入判定
{ length1=1; //相同长度即可以初始化为1
k=1;
while (k<Max) //在k不超过其最大长度的情况下遍历
{ if ((str1.s[i+k]==str2.s[j+k])&&(str1.s[i+k]!='\0'))
//在两字符串数组同时往后遍历k个单元依旧相同,且未到字符串结尾处'\0'
{ length1++; //相同字符串的长度加一
k++;} //继续往后遍历
else break;
//不满足str1.s[i+k]==str2.s[j+k])&&(str1.s[i+k]!='\0')条件就跳出循环
}
if (length1>length)
//比较相同字符串长度,存储最大字符串的长度和索引
{
index=i;
length=length1;
}
j+=length1;
//跳过已确定的相同字符串
}
else j++;
}
i++;
}
思路在文中进行了标注;
这个函数也是其中最重要的函数;
下面是完整代码及简单讲解:
类的声明:
#include <iostream>
#include <cstring>
using namespace std;//头文件声明
const int Max=1000;//设置最大长度
class Stringa
{
public:
Stringa( ) //不带形参的构造函数,目的为初始化
{len=0;
s=new char[Max];
}
Stringa(Stringa &m ) //复制构造函数,用于复制String这个类的对象
{len=m.len;
s=new char[Max]; //深复制,不仅仅只是地址复制
strcpy(s, m.s);
}
Stringa operator=(const Stringa &m) //赋值重载函数,用一个对象给另一个对象赋值
{ len=m.len;
s=new char[Max];
strcpy(s,m.s);
return (*this);
}
void getstring( ) //用于读入字符串的成员函数
{ cout<<"输入字符串: " ;
cin.getline(s, Max);
len=strlen(s);
}
void display( )
{ cout<<"字符串="<<s<<"(长度为"<<len<<")"<<endl; } //输出字符串并写出长度
friend Stringa maxsubstring(Stringa str1, Stringa str2);
//友元函数找最大公共子串的声明
~Stringa( ) //析构函数删除空间
{ delete [ ]s;}
private: //数据成员len代表长度,*s存储字符串
int len;
char *s;
};
找最大公共子串的函数:
Stringa maxsubstring(Stringa str1,Stringa str2)
{int index=-1,length=0,length1=0,i=0,j,k;
while (i<str1.len) //插入循环进行遍历处理
{ j=0; //每次下面数组遍历玩之后第一个字符串数组重新开始遍历
while(j<str2.len) //在不超过其长度的条件下遍历,超过就没有丝毫意义了
{
if (str1.s[i]==str2.s[j]) //当两者字符相同时进入判定
{ length1=1; //相同长度即可以初始化为1
k=1;
while (k<Max) //在k不超过其最大长度的情况下遍历
{ if ((str1.s[i+k]==str2.s[j+k])&&(str1.s[i+k]!='\0'))
//在两字符串数组同时往后遍历k个单元依旧相同,且未到字符串结尾处'\0'
{ length1++; //相同字符串的长度加一
k++;} //继续往后遍历
else break;
//不满足str1.s[i+k]==str2.s[j+k])&&(str1.s[i+k]!='\0')条件就跳出循环
}
if (length1>length)
//比较相同字符串长度,存储最大字符串的长度和索引
{
index=i;
length=length1;
}
j+=length1;
//跳过已确定的相同字符串
}
else j++;
}
i++;
}
Stringa temp;
if ((index!=-1)&&(length>0))
{ if (str1.s[index]==' ')
{ if (length==1) //当找到的公共子串中是空格时,也等同于没有找到公 共子串
{ temp.len=0;
temp.s[0]='\0';
return temp;
}
else // 当找到的公共子串的第一个字符是空格时,将第一个空格去掉后再将剩下的字符作为公共子串输出
{index+=1;
length-=1; }
}
if (str1.s[index+length-1]==' ') // 当找到的公共子串的最后一个字符是空格时,将最后一个空格去掉后再将剩下的字符作为公共子串输出
{ length-=1;}
for (int t=0;t<length;t++)
temp.s[t]=str1.s[index+t];
temp.len=length;
temp.s[length]='\0';
}
else //没有找到公共子串
{ temp.len=length;
temp.s[0]='\0';}
return temp;
}
主函数:
int main( )
{Stringa s1,s2,s3;
s1.getstring( );
s2.getstring( );
cout<<" s1";
s1.display( );
cout<<" s2";
s2.display( );
cout<<" s1和s2最长公共子";
s3=maxsubstring(s1,s2);
s3.display( );
return 0;
}
运行结果: