dutacm.club_1087_Common Substrings_(KMP)_(结合此题通俗理解kmp的next数组)

1087: Common Substrings

Time Limit:3000/1000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)
Total Submissions:849   Accepted:108
[Submit][Status][Discuss]

Description

You are given two long strings and B. They are comprised of lowercase letters. You should compute how many suffixes of A are the prefixes of B.

 

Input

In the first line is a number T (0<T100) , indicating the cases following.
In the next T lines each line contains two strings — A and B.
0<|A|10^5,0<|B|10^5)

 

Output

There should be exactly T lines.
Each line contain a number — the answer.

 

Sample Input

1
abcc ccba

Sample Output

2

HINT

In the first case, cc and c are two of the suffixes of string A, and they are the prefixes of string B.
 
题意:给两个字符串A和B,问A的所有后缀中,有多少个是B的前缀。
一看也是没思路啊。。。题解用的KMP,让我有点懵逼,仔细一想,让我更加理解之前学的kmp。
 
思路:利用kmp算法中求的next数组的过程即可得到答案,因为next的数组实质是:next[i]表示str[1--i]这个子串的前缀和后缀的最大公共长度(这里的前缀和后缀是之前看的kmp的博文中的定义,与普通的有细微差异)。
kmp算法利用这个数组,在失配时可以更加快地往后搜索(而不是从字符串的下一个字符开始重新与模式串的第一个字符开始匹配),next[i]的值即为模式串的第i+1个字符失配时将模式串向右移动至next[i]为当前要匹配的字符。因为模式串mo[i-next[i]+1,i](这是个后缀)这个子串与mo[1,next[i]](这是一个前缀)这个子串是一样的,所以将模式串右移至这个前缀代替这个后缀的位置,这样就达到了更加高效匹配的目的。结合博文看容易理解。。。
 
好题啊好题!!!!!!
 
#include <cstdio>
#include <cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
using namespace std;
#define N 100005
#define LL long long

char A[N],B[N],T[N<<1];
int Next[N<<1],lena,lenb,lent;

void getNext()
{
    int p=0;
    memset(Next,0,sizeof(Next));
    for(int i=2;i<lent;i++)
    {
        while(p>0&&T[p+1]!=T[i])
            p=Next[p];
        if(T[p+1]==T[i])
            p++;
        Next[i]=p;
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",A,B);
        lena=strlen(A);
        lenb=strlen(B);
        strcpy(T+1,B);
        T[lenb+1]='#';
        strcpy(T+lenb+2,A);
        T[lena+lenb+2]='\0';
        //cout<<T+1<<endl;
        lent=lena+lenb+2;
        getNext();
        //for(int i=1;i<lent;i++)
         //   cout<<Next[i]<<' ';
        //cout<<endl;
        int tmp=lent-1,res=0;
        while(tmp!=0)
        {
            if(Next[tmp]>0)
                res++;
            tmp=Next[tmp];
        }
        printf("%d\n",res);
    }
    return 0;
}

 

posted on 2017-03-13 21:12  JASONlee3  阅读(299)  评论(0)    收藏  举报

导航