2017/11/21
KMP字符串匹配的应用问题
KMP字符串匹配可参考上一篇博客。
问题描述:
给定一个字符串str1,只能往str1的后面添加字符变成str2。
要求1:str2必须包含两个str1,两个str1可以有重合,但是不能以同一个位置开头。
要求2:str2尽量短最终返回str2
思路
1、利用next数组,求出包含字符串str1最后一个字符的最大相同前缀后缀;
例如abracadabra,其最大的相同前后缀是abra,长度是4,
2、向str1尾部添加从最大相同前缀后开始到结尾的子串;
例如,abracadabra+cadabra,即从下标4开始的子串添加到str1末尾,即是所求的str2。
此次的next数组大小不再是str1的长度,而是长度+1,因为要包含最后一个字符。
代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
/* 2017/11/18 KMP扩展问题1: 给定一个字符串str1,只能往str1的后面添加字符变成str2。 要求1:str2必须包含两个str1,两个str1可以有重合,但是不 能以同一个位置开头。 要求2:str2尽量短 最终返回str2 */
#if 0
int getNext(string s)
{
vector<int>next(s.length() + 1);
next[0] = -1;
if (s.length() < 2)
return -1;
next[1] = 0;
int cn = 0;
int i = 2;
while (i<=s.length())
{
if (s[i - 1] == s[cn])
next[i++] = ++cn;
else if (cn <= 0)
next[i++] = 0;
else
cn = next[cn];
}
return next[next.size()-1];
}
string HaveTwice(string s)
{
if (s.length() == 0)
return "";
else if (s.length() == 1)
return s + s;
else if (s.length() == 2)
{
return s[0] == s[1] ? s + s.substr(1) : s + s;
}
return s + s.substr(getNext(s));
}
void main()
{
string s1 = "123ab123";
cout << HaveTwice(s1) << endl;
string s2 = "a";
cout << HaveTwice(s2) << endl;
string s3 = "aa";
cout << HaveTwice(s3) << endl;
string s4 = "ab";
cout << HaveTwice(s4) << endl;
string s5 = "abcdabcd";
cout << HaveTwice(s5) << endl;
string s6 = "abracadabra";
cout << HaveTwice(s6) << endl;
system("pause");
}
#else
#endif