文章标题 HDU 1841:Find the Shortest Common Superstring(KMP)

来源:互联网 发布:st单片机选型 编辑:程序博客网 时间:2024/04/29 13:51

Find the Shortest Common Superstring

Description

The shortest common superstring of 2 strings S 1 and S 2 is a string S with the minimum number of characters which contains both S 1 and S 2 as a sequence of consecutive characters. For instance, the shortest common superstring of “alba” and “bacau” is “albacau”.
Given two strings composed of lowercase English characters, find the length of their shortest common superstring.

Input

The first line of input contains an integer number T, representing the number of test cases to follow. Each test case consists of 2 lines. The first of these lines contains the string S 1 and the second line contains the string S 2. Both of these strings contain at least 1 and at most 1.000.000 characters.

Output

For each of the T test cases, in the order given in the input, print one line containing the length of the shortest common superstring.

Sample Input

2
alba
bacau
resita
mures

Sample Output

7
8

题意:给你两个字符串,求两个字符串连在一起的最短长度;比如,abcd和qwab的最短字符串为qwabcd,长度为6。
分析:此题为KMP内容,用两次KMP,将给出的字符串s1,s2,分别作为模式串和文本串,比如将s1作为模式串,然后找出s2的后缀有多少是s1的前缀,记录下来,比较两个的最大者,最后用两个字符串的总长度减去前缀与后缀相同的字符数。特别注意的是,得考虑,一个字符串包含另一个字符串的情况,比如bc和abcd。
代码:

#include<iostream>#include<string>#include<cstdio>#include<cstring>#include<vector>#include<math.h>#include<queue> #include<algorithm>using namespace std;const int Maxn=1000010;int n,m;char s1[Maxn],s2[Maxn],s[Maxn],text[Maxn];int fail[Maxn]; int match[Maxn];//以第一个为模式串,第二个为文本串 void KMP1(){    memset (fail,0,sizeof (fail));    memset (match,0,sizeof (match));    fail[0]=-1;    int p;    match[0]=0;    for (int i=1;i<=m;i++){        p=fail[i-1];        while (p>=0&&s[p+1]!=s[i]) p=fail[p];        if (p<0) fail[i]=0;        else fail[i]=p+1;    }    int ans=0;    for (int i=1;i<=n;i++){        p=match[i-1];        while (p>=0&&s[p+1]!=text[i]) p=fail[p];        if (p<0) match[i]=0;        else match[i]=p+1;    }}//以第二个为模式串,第一个为文本串 void KMP2(){    memset (fail,0,sizeof (fail));    memset (match,0,sizeof (match));    fail[0]=-1;    match[0]=0;    int p;    for (int i=1;i<=n;i++){//求fail数组         p=fail[i-1];        while (p>=0&&text[p+1]!=text[i]) p=fail[p];        if (p<0) fail[i]=0;        else fail[i]=p+1;    }       for (int i=1;i<=m;i++){        p=match[i-1];        while (p>=0&&text[p+1]!=s[i]) p=fail[p];        if (p<0) match[i]=0;        else match[i]=p+1;    }}int main (){    int total;    scanf ("%d",&total);    while (total--){        scanf ("%s",s1);        scanf ("%s",s2);        m=strlen (s1);        n=strlen (s2);        for (int i=1;i<=m;i++){//将字符串改为从下标为1开始的             s[i]=s1[i-1];        }        for (int i=1;i<=n;i++){            text[i]=s2[i-1];        }        int t1,t2;        KMP1();        t1=match[n];//求出文本串的后缀有多少个跟模式串的前缀一样         for (int i=1;i<=n;i++){//这是一个坑,有可能模式串包含在了文本串,比如bc跟abcd;             if (match[i]==m){                t1=m;            }        }        KMP2();        t2=match[m];//同上         for (int i=1;i<=m;i++){//同上             if (match[i]==n){                t2=n;            }        }        int ans=max(t1,t2);        printf("%d\n",m+n-ans);    }    return 0;}
0 0
原创粉丝点击