您的位置:首页 > 其它

Codeforces 25E 字符串hash模板题

2015-11-13 19:54 417 查看

题意

三个字符串,问最短的把这三个字符串的作为子串的字符串长度。

思路

三个字符串A(3,3)种排列方式,可以dfs,但是给定了三个,为方便起见,就手写了6种情况。

先判断三个串互相有没有为子串的情况,作为子串的就可以不被考虑了。

剩下的串,找前面串的后缀和后面串的前缀的最长公共部分。

这可以完全用kmp解决,但是为了练习字符串hash,所以就这么写了~

实现

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <iostream>
#include <map>
using namespace std;
string str[3];
string strTmp;
int type[6][3] = {0,1,2,0,2,1,1,0,2,1,2,0,2,0,1,2,1,0};
typedef unsigned long long ull;
const int maxn = 100005;
//或者100000007,一般取奇数即可
//先用长度比较,再用2~3个hash来判断,本题不需要这么做~
const ull B = 9973;

const int inf = 0x3f3f3f3f;
//判断str1后缀和str2前缀相等的最大长度
int cmp(string& str1,string& str2){
int ret = 0;
int len1 = str1.length();
int len2 = str2.length();
ull ah=0,bh=0,tmp=1;
for (int i=0;i<min(len1,len2);i++){
bh = bh * B + str2[i];
ah = ah + str1[len1-i-1] * tmp;
tmp *= B;
if (bh == ah){
ret = i+1;
}
}
return ret;
}
//判断str2是否为str1的子串
bool isInside(string& str1,string& str2){
int len1 = str1.length();
int len2 = str2.length();

ull t= 1;
for (int i=0;i<len2;i++)
t*=B;
ull ah = 0, bh = 0;
for (int i=0;i<len2;i++){
ah = ah * B + str2[i];
bh = bh * B + str1[i];
}
if (ah == bh)
return 1;
for (int i=0; i+len2 < len1 ;i++){
bh = bh * B + str1[i + len2] - str1[i] * t;
if (ah == bh)
return 1;
}
return 0;
}

int main(){
for (int i=0;i<3;i++)
cin>>str[i];
int ans = inf;
for (int i=0;i<6;i++){
int tmp = str[type[i][0]].length();
strTmp = str[type[i][0]];
for (int j=0;j<2;j++){
if (str[type[i][j+1]].length() <= strTmp.length()){
if (isInside(strTmp,str[type[i][j+1]]) == true){
continue;
}
}

int tt = cmp(strTmp,str[type[i][j+1]]);
tmp += str[type[i][j+1]].length() - tt;
strTmp += str[type[i][j+1]].substr(tt,str[type[i][j+1]].length());
}
ans = min(ans,tmp);
}
cout << ans <<'\n';
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: