Bazinga
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5088 Accepted Submission(s): 1606
Problem Description
Ladies and gentlemen, please sit up straight.
Don’t tilt your head. I’m serious.
For n given strings S1,S2,⋯,Sn, labelled from 1 to n, you should find the largest i (1≤i≤n) such that there exists an integer j (1≤j< i) and Sj is not a substring of Si.
A substring of a string Si is another string that occurs in Si. For example, ruiz" is a substring of
ruizhang”, and rzhang" is not a substring of
ruizhang”.
Input
The first line contains an integer t (1≤t≤50) which is the number of test cases.
For each test case, the first line is the positive integer n (1≤n≤500) and in the following n lines list are the strings S1,S2,⋯,Sn.
All strings are given in lower-case letters and strings are no longer than 2000 letters.
Output
For each test case, output the largest label you get. If it does not exist, output −1.
Sample Input
4
5
ab
abc
zabc
abcd
zabcd
4
you
lovinyou
aboutlovinyou
allaboutlovinyou
5
de
def
abcd
abcde
abcdef
3
a
ba
ccc
Sample Output
Case #1: 4
Case #2: -1
Case #3: 4
题意:给出n个串,当1~i-1之间任意一串不能与i匹配时,i满足条件,输出最大的i,如果都没有,输出-1
强行暴力,T了好几发,于是我开始考虑重复问题,一个串如果和另一个串能匹配,那么,这俩串只需要判断一次后者就行了,如果后者能匹配,那么前者一定能匹配。
那么如何判断这种串与串关系呢?多亏队友提醒,并查集啊!
我可以每次将这些互相包含的串加入一个集合中,这样每次匹配时,直接判断要匹配的串在不在一个集合里就行了,如果在的话,就不用匹配,如果不在,继续匹配;
还有,每次匹配的时候都要倒着来;因为只有倒着来,这个串包含前面的串,才能包含上面集合的判断条件,如果正着来,每次先和小串匹配,然后改变大串的集合,这显然是不满足条件的
然后,因为不知道,所给的串是不是长度严格递增的,加了一行判断,如果后面长度小于前面直接刷新(事实上后台数据是严格递增的),本来匹配是用find写的,百度说复杂度n*m,吓得我手敲了一遍KMP,结果find比KMP快,看来重复串比较多。。。
#include<bits/stdc++.h>
#define wtf printf("wtf\n");
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e6+20;
string s[505];
int nxt[2005];
int f[505],n;
void get_nxt(string t)
{
int i=0,j=-1,len=t.size();
nxt[0]=-1;
while(i<len)
{
if(j==-1||t[i]==t[j])
{
nxt[++i]=++j;
}
else
j=nxt[j];
}
}
bool kmp(string S,string T)
{
get_nxt(T);
int i=0,j=0,la=S.size(),lb=T.size();
while(i<la&&j<lb)
{
if(j==-1||S[i]==T[j])
{
i++,j++;
}
else
j=nxt[j];
}
if(j==lb)return true;
return false;
}
int getf(int x)
{
if(x==f[x])return x;
else
f[x]=getf(f[x]);
return f[x];
}
void mix(int x,int y)
{
int tx=getf(x);
int ty=getf(y);
if(tx!=ty)
{
f[tx]=ty;
}
}
void init()
{
for(int i=1; i<=n; i++)
f[i]=i;
}
int main()
{
std::ios::sync_with_stdio(false);
int t,q=0;
cin>>t;
while(t--)
{
cin>>n;
init();
for(int i=1; i<=n; i++)
{
cin>>s[i];
}
int now=-1,top=1;
for(int i=1; i<=n; i++)
{
for(int j=i-1; j>=1; j--)
{
if(getf(i)==getf(j))//判断是否同一集合
{
continue;
}
else
{
if(s[i].size()<s[j].size()||!kmp(s[i],s[j]))//长度小于前面或者出现不匹配
{
now=i;
break;
}
else
mix(i,j);//匹配成功,则加入同一集合
}
}
}
printf("Case #%d: %d\n",++q,now);
}
}