Marge: Yeah, what is it?
Homer: Take me for example. I want to find out if I have a talent in politics, OK?
Marge: OK.
Homer: So I take some politician’s name, say Clinton, and try to find the length of the longest prefix
in Clinton’s name that is a suffix in my name. That’s how close I am to being a politician like Clinton
Marge: Why on earth choose the longest prefix that is a suffix???
Homer: Well, our talents are deeply hidden within ourselves, Marge.
Marge: So how close are you?
Homer: 0!
Marge: I’m not surprised.
Homer: But you know, you must have some real math talent hidden deep in you.
Marge: How come?
Homer: Riemann and Marjorie gives 3!!!
Marge: Who the heck is Riemann?
Homer: Never mind.
Write a program that, when given strings s1 and s2, finds the longest prefix of s1 that is a suffix of s2.
The lengths of s1 and s2 will be at most 50000.
输入两个字符串,要求比对求出前一串的前缀与后一串的后缀相同的最长的部分,不过这题用kmp的方法我看了看大牛的思路。。。。。唉,想不到就是想不到啊T_T……
那就把这题作为kmp算法的讲解题吧。。。。。。
首先kmp是一个最基本的匹配算法,其目的最初是为了更高效率的匹配两串字符串看是否存在子串,然而子串本身其实就是应该有对应匹配规律可言的,所以我们在子串上面下点儿功夫之后再去匹配主串会将时间复杂度降的很低很低!百度上很多关于kmp的算法讲解,(orz虽然很多可是我最初看并没有看的多么懂)不过既然不懂我们就得多看,看得多了也就自然懂了,本来我只是准备个模板的,但想到博客上竟然没有kmp的模板代码,惭愧啊,所以先搞一个模板上来:
char p[50010],s[50010];//p[]是子串,s[]是主串
int pl,sl,next[50010];//pl代表子串长度,sl代表主串长度
void get_next()
{
int k=-1,j=0;
next[0]=-1;
while(j<pl)
{
if(k==-1||p[j]==p[k])
{
j++;
k++;
next[j]=k;
}
else
k=next[k];
}
}
int KMP()
{
int i=0,j=0,sum=0;
get_next();
while(j<pl&&i<sl)
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else j=next[j];
if(j==pl)
{
sum++;
j=next[j];
}
}
return sum;
}
这份代码表示的是求s[]主串中的子串p[]的个数,不过这份代码最初我们是不容易理解的,最好的办法是举个栗子跟着代码一步步看具体匹配的过程,这需要很大的耐心,不过,最重要的是看懂之后的喜悦了。如果看懂了,辣么基本思路其实也就掌握了。可是我们贴的这一题还没解决呢!所以我们来说说这一题。
首先要比对前缀和后缀,可是这并不涉及主串和子串的问题啊!于是我看了大牛的思路之后发现把找前缀的那一串字符添加到另一个字符串后面作为主串,接着用主串匹配找前缀的那个字符串,这就需要我们去理解kmp具体的过程了,其实理解了我说到这儿大家差不多就应该自己想想就能懂了,比如匹配asdf和sdfdfasd,我们首先把主串设为
sdfdfasdasdf,用这个主串去匹配asdf,具体操作建议自己动脑筋,不难想,只要看懂代码一切ok!
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
using namespace std;
char x1[50010],x2[100010];
int l1,l2,next[50010];
void getnext()
{
int kk=-1,jj=0;
next[0]=-1;
while(jj<l1)
{
if(kk==-1||x1[jj]==x1[kk])
{
jj++;
kk++;
next[jj]=kk;
}
else
kk=next[kk];
}
}
void KMP()
{
int i=0,j=0;
getnext();
//cout<<l2<<endl;
while(j<l1&&i<l1+l2)
{
if(j==-1||x2[i]==x1[j])
{
//cout<<i<<' '<<x2[i]<<' '<<j<<' '<<x1[j]<<endl;
i++;
j++;
}
else j=next[j];
if(i==l2)
{
if(j==-1||j==0)
cout<<0<<endl;
else
{
for(int k=0; k<j; k++)
cout<<x1[k];
cout<<' '<<j<<endl;
}
//cout<<j<<endl;
return ;
}
if(j==l1)
j=next[j];
}
}
int main()
{
while(cin>>x1>>x2)
{
memset(next,0,sizeof(next));
l1=strlen(x1),l2=strlen(x2);
strcat(x2,x1);
KMP();
}
return 0;
}