HDU-1238 Substrings (kmp)
题意:求出所有串(或者其逆置串)的最长公共子串
思路:不由的想到了 POJ-3080 Blue Jeans 这道题, 其题意是找到所有串的最长公共子串。也是暴力截取(取其中一个串)然后循环匹配(匹配时用kmp取优化)
这里多了一个(匹配其逆置,即将所有的串均逆置存入string数组中来循环匹配即可)
完整代码:
//字符串长为(1~100) 总字符串个数 n (1 <= n <= 100) #include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> using namespace std; const int N=500+5; const int M=500+5; string s[N]; string s1[N]; int nex[M]; void getnext(string str,int len){ int i=0,j=-1; nex[0]=-1; while(i<len){ if(j==-1||str[i]==str[j]) nex[++i]=++j; else j=nex[j]; } } bool kmp(string s1,int len1,string s2,int len2){ int i=0,j=0; while(i<len1){ if(j==-1||s1[i]==s2[j]) ++i,++j; else j=nex[j]; if(j==len2)return true; } //遍历完都没有找到 return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); int T,n; cin>>T; while(T--){ cin>>n; for(int i=0;i<n;i++)cin>>s[i]; string ans=""; for(int i=0;i<n;i++) s1[i].assign(s[i].rbegin(),s[i].rend()); for(int i=n;i<2*n;i++) { s[i] = s1[i-n]; } for(int i=0;i<s[0].size();i++) //起点 { for(int j=1;i+j<=s[0].size();j++) //终点 { string res=s[0].substr(i,j); getnext(res,res.size()); bool flag = false; for(int k=1;k<n;k++){ //匹配一次s再匹配一次逆s+n 然后再来判断最长 if(!(kmp(s[k],s[k].size(),res,res.size())||kmp(s[k+n],s[k+n].size(),res,res.size()))){ //正序串或者逆序串都没找到匹配之后,标记 flag = true; } } if(!flag) { if(ans.size()<res.size()) ans = res; } } } cout<<ans.size()<<endl; } return 0; }