Nikhil's Password
题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3459
模板:http://www.cnblogs.com/yujunyong/articles/2007809.html
Nikhil's Password
Total Submit: 62 Accepted: 13
Description
Nikhil's father has set a password on his computer to prevent Nikhil from playing games. The password is a string over the alphabet {a,b,..., z}. Nikhil's father is not sure if he will remember the password, so he decides to write it down. To ensure that the password is not obvious to someone reading the paper on which he has written it down, he hides it by writing three words on the paper. The actual password is the longest subword that is common to all these three words.
For instance, suppose Nikhil's father had written down the words aabbabbaba, abbabababa and bbabbabab. Then the hidden password is abbaba, since this is the longest common subword.
Your task is to help Nikhil find the password from the given set of three words. If there is more than one longest common subword, output the first one after they are in lexicographical order.
Input
The input consists of four lines. The first line of the input contains three integers M, N and K. The second line contains a word with M letters, the third line contains a word with N letters and the fourth line contains a word with K letters.
You may assume that N,M,K ≤ 2000
Output
A single line containing the longest common subword among the three input words. If there is more than one longest common subword, output the first one after they are in lexicographical order.
Sample Input
10 10 9
aabbabbaba
abbabababa
bbabbabab
Sample Output
abbaba
分析:
用KMP算法 快速找出每两个字符串的最长公共子串。再扩展到三个字符串的最长公共子串。之后输出字典序最小的最长公共子串。
代码:
View Code
#include<iostream>
#include<string>
using namespace std;
int const MAXN=2005;
int max(int a, int b)
{
return a>b ? a : b;
}
int min(int a, int b)
{
return a<b ? a : b;
}
void get_next(string sub, int *next, int len)
{
int k=-1, i;
next[0]=-1;
for (i=0; i<len; )
{
if (k==-1 || sub[i]==sub[k])
{
i++; k++;
if (sub[i]!=sub[k]) next[i]=k;
else next[i]=next[k];
}
else k=next[k];
}
}
int KMP(string str, string sub, int *next, int len1, int len2) //返回最大公共子串的长度
{
int i, j, sum=0;
for (i=0, j=0; i<len1 && j<len2; )
{
if (j==-1 || str[i]==sub[j])
{
i++; j++;
sum=max(sum, j);
}
else j=next[j];
}
return sum;
}
int compare(string s1, string s2, int n) //比较字符串s1和s2的大小(以字典序比较)如果s1>s2返回正值,s1<s2返回负值,s1==s2返回0
{
int i;
for (i=0; i<n; i++)
{
if (s1[i]!=s2[i]) return s1[i]-s2[i];
}
return 0;
}
int main()
{
string s1,s2,s3;
int len1,len2,len3;
while (cin>>len1>>len2>>len3)
{
cin>>s1>>s2>>s3;
int i;
int sublen[MAXN], next[MAXN];
for (i=0; i<len1; i++)
{
string _s1 = s1.substr(i);
//cout<<s1<<'\n'<<_s1<<'\n';
get_next(_s1, next, len1-i);
sublen[i]=min(KMP(s2, _s1, next, len2, len1-i), KMP(s3, _s1, next, len3, len1-i)); //求字符串_s1和字符串s2,s3的最大公共子串
}
/*for (i=0; i<len1; i++)
{
cout<<sublen[i]<<' ';
}cout<<endl;*/
int pos=0, max=0;
for (i=0; i<len1; i++) //求s1和s2,s3的最长公共子串
{
if (sublen[i]>max)
{
max=sublen[i];
pos=i;
}
}//cout<<max<<' '<<pos<<'\n';
for (i=0; i<len1; i++) //在所有最长公共子串中找出字典序最小的最长公共子串
{
if (sublen[i]==max)
{
string _s1 = s1.substr(i);
string s1_pos = s1.substr(pos);
if (compare(_s1, s1_pos, max)<0)
{
pos=i;
}
}
}
for (i=pos; i<pos+max; i++) //输出符合要求的字符串
{
cout<<s1[i];
}
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号