HDU Bazinga(KMP+并查集)

来源:互联网 发布:sql在线格式化 实现 编辑:程序博客网 时间:2024/06/05 19:41

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 ofruizhang”, and rzhang" is not a substring ofruizhang”.

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);    }}
原创粉丝点击