题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2594
题目描述:
给定两个字符串s1,s2,问是否存在一个最长的子串,使得这个子串既是s1的前缀又是s2的后缀。
题解:
既然是要求s1的前缀与s2后缀,那么只要将s1与s2合并成一个字符串str,再来对这个字符串进行一波kmp就可以知道题目要求的前后缀是否存在了。
字符串的合并最方便的是string,所以用C++的做法做这道题。
不过这种做法要注意的是,如果s1与s2的内容相同,那么最终会得到超过s1与s2的子串,这明显是不可以的,所以在最终输出时要比较子串长度与s1、s2长度。
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <vector> 7 #include <algorithm> 8 using namespace std; 9 10 #define ll long long 11 #define INF 0x3f3f3f3f3f 12 #define MAX 100100 13 14 int fail[MAX]; 15 16 void getFail(string str) 17 { 18 int len = str.size(); 19 fail[0] = 0; 20 int k = 0; 21 for(int i = 1; i < len; ++i) { 22 while(k > 0 && str[i] != str[k]) 23 k = fail[k-1]; 24 if(str[i] == str[k]) 25 k++; 26 fail[i] = k; 27 } 28 } 29 30 int main() 31 { 32 //freopen("debug\in.txt", "r", stdin); 33 //freopen("CON", "w", stdout); 34 int i, j, k; 35 string s1, s2; 36 while(cin >> s1 >> s2) { 37 memset(fail, 0, sizeof(fail)); 38 string str = s1 + s2; 39 getFail(str); 40 41 int ans = fail[str.size()-1]; 42 string tmp; 43 int minw = min(s1.size(), s2.size()); 44 for(i = 0; i < ans && i < minw; ++i) { //"i < minw"是防止子串长度超出原串 45 tmp += str[i]; 46 } 47 if(!ans) 48 cout << ans << endl; 49 else 50 cout << tmp << " " << min(minw, ans) << endl; 51 } 52 return 0; 53 } 54 55 /* 56 input: 57 abcabcabcabc 58 abcabcabcabcabc 59 abcabc 60 abc 61 clinton 62 homer 63 riemann 64 marjorie 65 66 output: 67 abcabcabcabc 12 68 abc 3 69 0 70 rie 3 71 */