【HDU - 1238】 F - Substrings (KMP)

topic:

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


Ideas:

Divide the first string into various combinations

For example, ABCD, divided into A, B, C, D, AB, BC, CD, ABC, BCD, ABCD,

Then these substrings themselves and the flipped substrings are judged by kmp whether they can be matched in all subsequent strings , and the longest substring that meets the requirements is found from them.


Code:

#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;
}

Guess you like

Origin blog.csdn.net/weixin_45260385/article/details/108202453