【NOIP2017模拟12.3】子串

来源:互联网 发布:淘宝商城牛仔男装裤子 编辑:程序博客网 时间:2024/05/22 07:59

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

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

4
-1
4
3

Data Constraint

t<=50,n<=500,|Si|<=2000

Solution

一看到题,多字符串匹配!这不就是不久前才打过的AC自动机吗?自信满满能AC

结果出来,才50分??经过思考发现,AC自动机好像过不了

正解:暴力!
从第一个到最后一个暴力,每一个再和以前的匹配(用KMP)
显然,如果a是b的字串,b是c的字串,那么a是c的字串
所以当我找到一个匹配的字串(假设i是j的字串),那么以后再匹配时就不用管i了,只用去看看j是不是当前新匹配的字串就行了,那么感性理解一下,每一个字符串匹配只有一次,就可以过了

Code

#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#define N 700#define cl(a) memset(a,0,sizeof(a))#define fo(i,a,b) for(int i=a;i<=b;i++)int next[N][2010],bz[N],m[N],n;char a[N][2010];void gn(int k){    int j=0;    fo(i,2,m[k])    {        while(j>0&&a[k][j+1]!=a[k][i]) j=next[k][j];        if(a[k][j+1]==a[k][i]) j++;        next[k][i]=j;    }}bool kmp(int k,int l){    int j=0;    if(m[k]>m[l]) return 0;    fo(i,1,m[l])    {        while(j>0&&a[k][j+1]!=a[l][i]) j=next[k][j];        if(a[k][j+1]==a[l][i]) j++;        if(j==m[k]) return 1;    }    return 0;}int main(){    freopen("sub.in","r",stdin);freopen("sub.out","w",stdout);    int ac;    for(scanf("%d",&ac);ac;ac--)    {        int ans=-1;        memset(bz,0,sizeof(bz));memset(next,0,sizeof(next));        scanf("%d\n",&n);        fo(i,1,n)        {            scanf("%s\n",a[i]+1);            m[i]=strlen(a[i]+1);            gn(i);        }        fo(i,2,n)        {            fo(j,1,i-1)            if(!bz[j])            {                if(kmp(j,i)) bz[j]=1;                else                {                    ans=i;break;                }            }        }        printf("%d\n",ans);    }}
0 0
原创粉丝点击