1 题目
问题 A: 求最长公共子串(串)
[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB
题目描述
求采用顺序结构存储的串s和串t的一个最长公共子串,若没有则输出false,若最长的有多个则输出最先出现的那一串。
输入
输入两个字符串
输出
输出公共子串
样例输入 Copy
abcdef
adbcef
样例输出 Copy
bc
2 解析
2.1 题意
求两个字符串最长的公共子串
2.2 思路
对两个字符串的每个子串求出hash值(同时记录最长长度,起始长度、结束长度),然后找出两堆子串对应hash值中相等的那些,便可以找到最大长度以及最大长度对应的子串的起始和终止位置。时间复杂度为O(n2+m2),n和m为两个字符串的长度。
3 参考代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::max;
using std::string;
using std::vector;
using std::cin;
typedef long long LL;
struct Node{
int hashValue, length, start, end;//字符串hash值、长度、起始为止、终止位置
Node(int _hashValue, int _length, int _start, int _end): hashValue(_hashValue), length(_length), start(_start), end(_end){}
};
const int P = 10000019;
const int MOD = 1000000007;
const int MAXN = 1010;
LL PowP[MAXN];//powP存放P^i%MOD
LL H1[MAXN], H2[MAXN];//str1、str2的hash值
vector<Node> pr1, pr2;//<子串hash值,子串长度>
//初始化PowP
void Init(int len){
PowP[0] = 1;
for (int i = 1; i <= len; ++i)
{
PowP[i] = (PowP[i-1] * P) % MOD;
}
}
//str的hash
void calH(LL H[],string &str){
H[0] = str[0];
for (int i = 1; i < str.length(); ++i)
{
H[i] = (H[i-1] * P + str[i]) % MOD;
}
}
//计算H[i...j]
int calSingleSubH(LL H[], int i, int j){
if(i == 0) return H[j];
else return ((H[j] - H[i-1] * PowP[j - i + 1]) % MOD + MOD)% MOD;
}
//计算所有子串的hash值,并将<子串hash,子串长度>存入pr
void calSubH(LL H[], int len, vector<Node>& pr){
for (int i = 0; i < len; ++i)
{
for (int j = i; j < len; ++j)
{
int hashValue = calSingleSubH(H, i, j);
pr.push_back(Node(hashValue, j - i + 1, i , j));
}
}
}
//计算pr1和pr2中相同hash值,维护最大长度
string getMax(string str1){
int ans = 0;
string str;
for (int i = 0; i < pr1.size(); ++i)
{
for (int j = 0; j < pr2.size(); ++j)
{
if(pr1[i].hashValue == pr2[j].hashValue){
if(pr1[i].length > ans){
ans = pr1[i].length;
str = str1.substr(pr1[i].start, pr1[i].end);
}
}
}
}
return str;
}
int main(int argc, char const *argv[])
{
string str1, str2;
getline(cin, str1);
getline(cin, str2);
Init(max(str1.length(), str2.length()));
calH(H1, str1);
calH(H2, str2);
calSubH(H1, str1.length(), pr1);
calSubH(H2, str2.length(), pr2);
string res = getMax(str1);
if(res.size() == 0){
printf("false\n");
}else{
std::cout << res << std::endl;
}
return 0;
}