题目描述
小明有两个字符串,分别为 S,T。
请你求出 T 串的前缀在 S 串中出现的最长长度为多少。
输入描述
输入包含两行,每行包含一个字符串,分别表示 S,T。
1 < |S|,|T| < 10^6 ,保证 S,T 只包含小写字母。
输出描述
输出共 1 行,包含一个整数,表示答案。
代码来自《程序设计竞赛专题挑战教程》
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int Next[N];
void getNext(string p) //计算Next[1]~Next[plen]
{
Next[0]=0; Next[1]=0;
for(int i=1; i<p.size(); i++) //把i的增加看成后缀的逐步扩展
{
int j=Next[i]; //j的后移:j指向匹配区间的后一个字符
while(j && p[i]!=p[j]) //后一个字符不相同
{
j=Next[j];
}
if(p[i]==p[j]) Next[i+1]=j+1;
else Next[i+1]=0;
}
}
int kmp(string s,string p) //在 S中找 p
{
int ans=0;
int slen=s.size(), plen=p.size();
int j=0;
for(int i=0; i<slen; i++) //匹配s和p的每一个字符
{
while(j && s[i]!=p[j]) //失配
j=Next[j]; //j滑动到Next位置
if(s[i]==s[j]) //匹配,继续
{
j++;
ans=max(ans,j); //统计最长匹配
}
if(j==plen) //j到了p的结尾,找到了一个完全匹配
//这个匹配,在s中的起点是i+1-plen,末尾是i 有需要可以输出:
//printf("at location=%d, %s\n", i+1-plen,&s[i+1-plen]);
return ans; //最长前缀就是p的长度,直接返回
}
return ans; //返回p在s中出现的最长前缀
}
int main()
{
string s,t;
cin>>s>>t;
getNext(t); //预计算Next[]数组
cout<<kmp(s,t);
return 0;
}