1 给定一个query和一个text,均由小写字母组成。要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度。例如,query为 “acbac”,text为”acaccbabb”,那么text中的”cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3。
#include <iostream>
#include <string>
using namespace std;
int main()
{
// string query="acbac";
// string text="acaccbabb";
string query,text;
getline(cin,query);
getline(cin,text);
int query_len=query.length();//得到字符串query长度
int text_len=text.length();//得到字符串text的长度
/*从query字符串第一个字母开始,当有字母与text字符串
相同时,比较接下来的字符是否相同,若相同,计数加一,
否则跳出当前循环,寻找下一个相同字符*/
int i = 0, j = 0,result=0;
int u,v,count;
for(i = 0; i<query_len; i++)
{
for(j = 0; j<text_len; j++)
{
if(query[i] == text[j])
{
u=i;
v=j;
count = 0;
while(query[u++] == text[v++])
{
count++;
if((u>=query_len)||(v>=text_len))
break;
}
if(result<count)
result=count;
}
}
}
cout<<result<<endl;
return 0;
}
2 给出两个字符串,用自己最熟悉的编程语言找出两个字符串中匹配最长的字符串。如:“ascdefd”和“abcdef”则匹配出的最大字符串为:cdef。
使用动态规划
#include <iostream>
#include <string>
using namespace std;
string lcs_search(string str1, string str2)
{
int length = 0;
int end = 0;
if (str1.length() < str2.length()) //保证str1为母串(较长的哪个串)
{
string strTemp = str1;
str1 = str2;
str2 = strTemp;
}
int * sign = new int[str1.length()];
//sign里存储的是母串(str1)每个元素前向能与子串匹配的公共子串数
for (int i = 0; i < str2.length(); i++)
{
for (int j = str1.length() - 1; j >= 0; j--)
{
if (str2[i] == str1[j])
{
if (i == 0 || j == 0) //i==0,则母串的j元素必然只能匹配一个,j==0同理
sign[j] = 1;
else //由于该次j匹配,所以子串可以+1
sign[j] = sign[j - 1] + 1;
}
else //不匹配,则此位置的sign归零
sign[j] = 0;
if (sign[j] > length) //结果存储
{
length = sign[j];
end = j;
}
}
}
delete []sign;
return str1.substr(end - length + 1, length);
}
int main()
{
string a="abcdef",b="ascdefd";
string c;
c=lcs_search(a,b);
cout<<c<<endl;
return 0;
}
分析
str1 “ascdefd”;str2 “abcdef”
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | length | end |
---|---|---|---|---|---|---|---|---|---|
‘a’ | ’s’ | ‘c’ | ‘d’ | ‘e’ | ‘f’ | ‘d’ | length | end | |
‘a’ | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
‘b’ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
‘c’ | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
‘d’ | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 2 | 3 |
‘e’ | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 3 | 4 |
‘f’ | 0 | 0 | 2 | 0 | 0 | 4 | 0 | 4 | 5 |
如果是N个字符串,可以选择遍历
#include <iostream>
#include <string>
using namespace std;
//将第一个字符串与最短的字符串交换
void swap(string *pStr,int i)
{
string temp;
temp = *pStr;
*pStr = *(pStr + i);
*(pStr + i) = temp;
}
int main()
{
int N;
cout << "请输入N(控制字符串个数):";
cin >> N;
cout << "请输入" << N << "个字符串"<<endl;
string *pStr;
pStr = new string [N];
int i,min;
int maxLen = 1000;
//找出输入的字符串中长度最小的串,并把最小串序号记在min中
for(i = 0; i < N; ++i){
cin >> *(pStr + i);
int len = (*(pStr +i)).length();// *操作符与调用函数的.操作符优先级问题,.优先级高于*,所以必须加上()
if(len < maxLen){
maxLen = len;
min = i;
}
}
swap(pStr,min);
/*
for(i = 0; i < N; ++i)
cout << *(pStr + i) << endl;
*/
int len0 = pStr[0].length();
int j,k,maxlen= 0;
string maxStr;
string tmpStr;
for(i = 0; i < len0 && maxlen <= len0 - i -1; ++i)
{
for(j = 0; j < len0 && maxlen <= len0 - i -j - 1; ++j)
{
tmpStr = pStr[0].substr(i,len0 - j);//对字符串数组中第一个子串,求出其可能的子串值,如果剩余子串长度小于maxlen则不用去求了,for循环中给出了限制
//将子串tmpStr与参与匹配的字符串比较,判断tmpStr是否为剩余串的子串,如果不是则break出循环
for(k = 1; k < N; ++k)
{
string::size_type pos1 = pStr[k].find(tmpStr);
if(pos1 < pStr[k].length())
continue;
else
break;
}
if(k == N)//说明子串tmpStr是其他参与匹配的子串的子串
{
if(tmpStr.length() > maxlen)//tmpStr如果是当前最大的子串,则记录下来
{
maxlen = tmpStr.length();
maxStr = tmpStr;
}
}
}
}
cout << "最大公共子串为:";
cout << maxStr <<endl;
delete []pStr;
return 0;
}
m=length of min string,则复杂度:O(m*m*N)
持续更新中。。。