【 HDU - 1238 】F - Substrings (KMP)

题目:

You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.
Input
The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.
Output
There should be one line per test case containing the length of the largest string found.
Sample Input
2
3
ABCD
BCDFF
BRCD
2
rose
orchid
Sample Output
2
2


思路:

把第一个字符串,切分成各种组合

比如ABCD,切分为A,B,C,D,AB,BC,CD,ABC,BCD,ABCD,

然后将这些子串本身翻转后的子串通过kmp判断是否在后面的所有字符串中都能匹配上,从中找出符合要求的最长子串。


代码:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int t,n,Next[110]; //next数组
void getNext(string s) //获取next数组的值(模板)
{
    
    
	int len=s.size(),j=-1;
	fill(Next,Next+110,0);
	Next[0]=-1;
	for(int i=1;i<len;i++)
	{
    
    
		while(j!=-1 && s[i]!=s[j+1]){
    
     //直到匹配上或者到-1
			j=Next[j];
		}
		if(s[i]==s[j+1]) j++;
		Next[i]=j;
	}
}

int kmp(string s1,string s2) //kmp
{
    
    
	int len1=s1.size(),len2=s2.length(),j=-1;
	getNext(s2); //先得到s2的next数组
	for(int i=0;i<len1;i++)
	{
    
    
		while(j!=-1 && s1[i]!=s2[j+1]){
    
     //直到匹配上或者到-1
			j=Next[j];
		}
		if(s1[i]==s2[j+1]) j++;
		if(j==len2-1) return 1; //匹配成功,返回true
	}
	return 0;
}


int main()
{
    
    
	cin>>t;
	while(t--)
	{
    
    
		string s[110];
		int ans=0;
		cin>>n;
		for(int i=0;i<n;i++) cin>>s[i];
		for(int i=0;i<s[0].size();i++) //以i开头
		{
    
    
			for(int j=1;j<=s[0].length();j++) //以j结尾
			{
    
    
				string t;
				for(int k=i;k<j;k++) t+=s[0][k]; //从i遍历到j-1
				if(t.size()) //子串存在
				{
    
    
					int flag=0; //标记是否有匹配不上的
					for(int l=1;l<n;l++)
					{
    
    
						string tt=t;
						reverse(tt.begin(),tt.end()); //翻转
						if(!kmp(s[l],t) && !kmp(s[l],tt)) 
						{
    
    
							flag=1; //本身和翻转后都没匹配上,标记flag
							break; //出现匹配不上,后面就不用继续了
						}
					}
					if(!flag) if(t.size()>ans) ans=t.size(); //flag为0,都匹配上了,找出符合的最长子串
				}
			}
		}
		cout<<ans<<endl;
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45260385/article/details/108202453