问题 A: 求最长公共子串(串)

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;
}
发布了377 篇原创文章 · 获赞 52 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_33375598/article/details/104472568