HDU-5510 Bazinga、HDU-5521 Meeting

来源:互联网 发布:淘宝差评拦截在哪设置 编辑:程序博客网 时间:2024/06/05 18:22

Bazinga

 题意:给你n个字符串,问你一个最大的i,使得前i-1个字符串至少有一个不是这个串的子串,如果不存在,输出-1。

队友用kmp+链表优化过的,虽然不懂他的思路,不过模拟赛的时候A了也没多想。

当时我的思路是:对所有的字符串按长度排序,这样可以优化长度乱序的情况,然后比较相邻两个,如果前一个不是后一个的子串就把前一个串存起来,更新答案,每次比较先与前一个比较,符合的话再和存起来的串比较,不符合把前一个存起来,更新答案。

代码一:只存一个 WA。

const int N=2e6+10;void kmp_pre(char x[],int m,int next[]){    int i,j;    j=next[0]=-1;    i=0;    while(i<m)    {        while(-1!=j&&x[i]!=x[j]) j=next[j];        next[++i]=++j;    }}int nex[2010];bool judge(char x[],char y[]){    int i=0,j=0;    int m=strlen(x);    int n=strlen(y);    kmp_pre(x,m,nex);    while(i<n)    {        while(-1!=j&&y[i]!=x[j]) j=nex[j];        i++,j++;        if(j>=m) return true;    }    return false;}char s[501][2010];int main(){    int t,n;    scanf("%d",&t);    int t1=t;    while(t--)    {        scanf("%d",&n);        for(int i=1; i<=n; i++) scanf("%s",s[i]);        int tmp=-1,ans=-1;        for(int i=2; i<=n; i++)        {            if(!judge(s[i-1],s[i]))            {                ans=i;                tmp=i-1;            }            else            {                if(tmp!=-1&&!judge(s[tmp],s[i])) ans=i;            }//            printf("i=%d ans=%d\n",i,ans);        }        printf("Case #%d: %d\n",t1-t,ans);    }    return 0;}

代码二:把所有不符合的存起来,暴力判 746ms AC:

const int N=2e6+10;void kmp_pre(char x[],int m,int next[]){    int i,j;    j=next[0]=-1;    i=0;    while(i<m)    {        while(-1!=j&&x[i]!=x[j]) j=next[j];        next[++i]=++j;    }}int nex[2010];bool judge(char x[],char y[]){    int i=0,j=0;    int m=strlen(x);    int n=strlen(y);    kmp_pre(x,m,nex);    while(i<n)    {        while(-1!=j&&y[i]!=x[j]) j=nex[j];        i++,j++;        if(j>=m) return true;    }    return false;}char s[501][2010];int tmp[501];int main(){    int t,n;    scanf("%d",&t);    int t1=t;    while(t--)    {        scanf("%d",&n);        for(int i=1; i<=n; i++) scanf("%s",s[i]);        int num=0,ans=-1;        for(int i=2; i<=n; i++)        {            if(!judge(s[i-1],s[i]))            {                ans=i;                tmp[num++]=i-1;            }            else            {                for(int j=0; j<num; j++)                    if(!judge(s[tmp[j]],s[i]))                    {                        ans=i;                        break;                    }            }        }        printf("Case #%d: %d\n",t1-t,ans);    }    return 0;}
strstr函数却更优,546ms AC:

strstr原理:字符串匹配two way算法 复杂度O(1)啊。

char s[501][2010];int tmp[501];int main(){    int t,n;    scanf("%d",&t);    int t1=t;    while(t--)    {        scanf("%d",&n);        for(int i=1; i<=n; i++) scanf("%s",s[i]);        int num=0,ans=-1;        for(int i=2; i<=n; i++)        {//            if(!judge(s[i-1],s[i]))            if(strstr(s[i],s[i-1])==NULL)            {                ans=i;                tmp[num++]=i-1;            }            else            {                for(int j=0; j<num; j++)//                    if(!judge(s[tmp[j]],s[i]))                    if(strstr(s[i],s[tmp[j]])==NULL)                    {                        ans=i;                        break;                    }            }        }        printf("Case #%d: %d\n",t1-t,ans);    }    return 0;}


Meeting

近阶段做过最有意思的一个题,目前见过所有图论中很有意思的一个题,被网络流的思想缠绕了很久,最后才想明白建图然后一发板子AC。

 题意:两个人分别在1号点和n号点,有m个集合,每个集合里有Si个点,任意两个点之间需要Ti的时间到达。给你n,然后m个集合的信息,求两个人同时出发到一个点的最短时间,如果最短时间有多种方案,从小到大输出这些可行点。

思路:由数据范围可以推测任意两个之间建边是行不通的,于是我们可以把每个集合虚拟一个点,虚拟点到这个集合的每个点的长度为Ti,点到虚拟点的长度为0。从1出发跑一遍最短路,从n出发跑一遍最短路,每个点上所需的时间就是1号点到这个点的时间与n号点到这个点时间的最大值。

建边的思想很强,当时想着用网络流跑费用流,但这个可行点却不知道怎么求,但将网络流的建图思想用到最短路上,getAC。

const int N=2e6+10;struct Edge{    int to,next;    ll w;} e[N*2];int n,m,tot,cnt,head[N],vis[N];ll d1[N],d2[N];struct node{    int v;    ll c;    friend bool operator <(node a,node b)    {        return a.c>b.c;    }};priority_queue<node>q;void init(){    for(int i=1; i<=cnt; i++) d1[i]=d2[i]=INF;    d1[1]=0,d2[n]=0;}void add(int u,int v,ll w){    e[tot].to=v,e[tot].w=w;    e[tot].next=head[u];    head[u]=tot++;}void  dij(int s,int f){    while(!q.empty()) q.pop();    memset(vis,0,sizeof(vis));    if(f==1) q.push(node {s,d1[s]});    else q.push(node {s,d2[s]});    while(!q.empty())    {        node tmp=q.top();        q.pop();        int x=tmp.v;        if(vis[x]) continue;        vis[x]=1;        for(int i=head[x]; i+1; i=e[i].next)        {            int v=e[i].to;            ll w=e[i].w;            if(f==1)            {                if(d1[v]>d1[x]+w)                {                    d1[v]=d1[x]+w;                    q.push(node {v,d1[v]});                }            }            else            {                if(d2[v]>d2[x]+w)                {                    d2[v]=d2[x]+w;                    q.push(node {v,d2[v]});                }            }        }    }}int SA[N];int main(){    int t;    scanf("%d",&t);    int t1=t;    while(t--)    {        scanf("%d%d",&n,&m);        tot=0,cnt=n;        memset(head,-1,sizeof(head));        int ti,num,x;        for(int i=1; i<=m; i++)        {            scanf("%d%d",&ti,&num);            ++cnt;            for(int j=0; j<num; j++)            {                scanf("%d",&x);                add(cnt,x,ti);                add(x,cnt,0);            }        }        init();        dij(1,1);        dij(n,2);        ll ans=INF;        int AAA=0;        for(int i=1; i<=n; i++)ans=min(ans,max(d1[i],d2[i]));        for(int i=1; i<=n; i++)        {            ll TT=max(d1[i],d2[i]);            if(TT==ans) SA[AAA++]=i;        }        printf("Case #%d: ",t1-t);        sort(SA,SA+AAA);        if(ans==INF) puts("Evil John");        else        {            printf("%lld\n",ans);            for(int i=0; i<AAA; i++)                printf("%d%c",SA[i],i==AAA-1?'\n':' ');        }    }    return 0;}



原创粉丝点击