[各種面試題] 重疊的最長子串

重疊的最長子串:

題目描述:

給定兩個字符串,求它們前後重疊的最長子串的長度,比如"abcde"和“cdefg”是"cde",長度爲3。

輸入:

輸入可能包含多個測試案例。
對於每個測試案例只有一行, 包含兩個字符串。字符串長度不超過1000000,僅包含字符'a'-'z'。

輸出:

對應每個測試案例,輸出它們前後重疊的最長子串的長度。

樣例輸入:
abcde cdefg
樣例輸出:
3
 第一反應還是後綴數組,把a跟b串起來,求後綴數組的h數組,之後找答案的時候就找b源串這個後綴然後跟a起始的某個後綴的h的最小值中的最大值,應該是這樣。想一想這一步在求得h之後能否在線性時間求得。。。


後綴數組先放一放,另外想了下,覺得跟KMP是很相似的,就是求某一個後綴跟某一個前綴最大相似長度,其實就是KMP的第一部,構造PRE數組。首先是構造新串  t= b+a;這樣就變成a的後綴跟b的前綴最大相似長度了。

注意最後返回的時候不能直接返回pre[t.length()-1]+1, 還要判斷是否超過a的長度。

#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<climits>
#include<algorithm>
using namespace std;

char a[1000005];
char b[1000005];

int longestCover(string& a,string& b)
{
	string t(b+a);
	vector<int> pre(t.length(),-1);
	for(int i=1;i<t.length();i++)
	{
		int p=pre[i-1];
		while(p!=-1&&t[p+1]!=t[i])
			p=pre[p];
		if(t[p+1]==t[i])
			pre[i]=p+1;
	}
	return min((int)a.length(),pre[t.length()-1]+1);
}
int main()
{
	while(scanf("%s%s",a,b)!=EOF)
	{
		string aa(a),bb(b);
		int ans=longestCover(aa,bb);
		printf("%d\n",ans);
	}
}

然後看了下題解,人家用的是擴展KMP,思想跟KMP很像,但是我覺得更像最大回文子串,都是利用已經得到的範圍來更新當前值。

這裏有張圖,看了就比較容易理解了:

http://blog.sina.com.cn/s/blog_6974c8b20101054d.html


擴展KMP的兩步很相似。

#include<iostream>
#include<vector>
#include<string>
using namespace std;

int getLonestCover(string& s,string& t)
{
	vector<int> a(t.length(),0);
	a[0]=t.length();
	int len=0;
	while(1+len<t.length()&&t[len]==t[1+len])
		len++;
	a[1]=len;
	int k=1,mx=k+a[k]-1;
	for(int i=2;i<t.length();i++)
	{
		int w=i-k;
		if(i+a[w]-1<mx)
			a[i]=a[w];
		else
		{
			int len=max(0,mx-i+1);
			while(i+len<t.length()&&t[0+len]==t[i+len])
				len++;
			a[i]=len;
			k=i,mx=i+a[i]-1;
		}
	}
	vector<int> b(s.length(),0);
	len=0;
	while(len<s.length()&&len<t.length()&&s[len]==t[len])
		len++;
	b[0]=len;
	k=0,mx=len-1;
	for(int i=1;i<s.length();i++)
	{
		int w=i-k;
		if(i+a[w]-1<mx)
			b[i]=a[w];
		else
		{
			int len=max(0,mx-i+1);
			while(i+len<s.length()&&len<t.length()&&s[i+len]==t[len])
				len++;
			b[i]=len;
			k=i,mx=i+b[i]-1;
		}
	}
	int ans=0;
	for(int i=0;i<s.length();i++)
		if(b[i]==s.length()-i)
		{
			ans=b[i];
			break;
		}
	return ans;
}
int main()
{
	string a,b;
	while(cin>>a>>b)
	{
		int ret=getLonestCover(a,b);
		cout<<ret<<endl;
	}
}


然後貼一個擴展KMP的題:http://blog.csdn.net/xingyeyongheng/article/details/9386671

發佈了215 篇原創文章 · 獲贊 6 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章