题意:
给定三个串,求包含这三个串的总串的最小长度。
思路:
字符串哈希。
当然,也可以用KMP,然而我自己没有想到,看来对KMP的理解仍然不够深。
这里也引用一下其他博主的KMP做法。
http://blog.csdn.net/u011345136/article/details/38400395
实现:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const ull B = 1e8 + 7;
const int MAX_SIZE = 1e5 + 10;
const int INF = 0x3f3f3f3f;
char s[3][MAX_SIZE];
int ans;
int type[6][3] = {0,1,2,0,2,1,1,0,2,1,2,0,2,0,1,2,1,0};
bool contain(char* a, char* b)//a是否在b中出现过
{
int al = strlen(a), bl = strlen(b);
if(al > bl) return false;
//计算B的al次方
ull t = 1;
for(int i = 0; i < al; i++) t *= B;
//计算a和b长度为al的前缀对应的哈希值
ull ah = 0, bh = 0;
for(int i = 0; i < al; i++) ah = ah * B + a[i];
for(int i = 0; i < al; i++) bh = bh * B + b[i];
//对b不断右移一位,更新哈希值并判断
for(int i = 0 ; i + al <= bl; i++)
{
if(ah == bh) return true; //b从位置i开始长度为al的字符串子串等于a
if(i + al < bl) bh = bh * B + b[i + al] - b[i] * t;
}
return false;
}
//a的后缀和b的前缀相等的最大长度
int overlap(char* a, char* b)
{
int al = strlen(a), bl = strlen(b);
int ans = 0;
ull ah = 0, bh = 0, t = 1;
for(int i = 1; i <= min(al, bl); i++)
{
ah = ah + a[al - i] * t;
bh = bh * B + b[i - 1];
if(ah == bh) ans = i;
t *= B;
}
return ans;
}
void solve()
{
ans = INF;
int l1 = 0, l2 = 0;
for(int i = 0; i < 6; i++)
{
if(contain(s[type[i][0]], s[type[i][1]]))
{
l1 = strlen(s[type[i][0]]);
}
else
{
l1 = overlap(s[type[i][0]], s[type[i][1]]);
}
if(contain(s[type[i][2]], s[type[i][1]]))
{
l2 = strlen(s[type[i][2]]);
}
else
{
l2 = overlap(s[type[i][1]], s[type[i][2]]);
}
ans = min(ans, (int)(strlen(s[0]) + strlen(s[1]) + strlen(s[2]) - l1 - l2));
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> s[0] >> s[1] >> s[2];
solve();
return 0;
}