HDU-#4096 Universal Question Answering System(字符串+路径判断)

本文探讨了一种解决名词间关系问题的算法,通过构建图并进行路径搜索,有效识别陈述句与疑问句中名词之间的联系。适用于处理复杂的语言逻辑问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题目大意:给出一些陈述句描述名词与名词或动词之间的关系,再给出一些疑问句询问名词与名词或动词之间的关系是否存在。

        解题思路:自己写了一个版本,提交了20多次都没有找到WA在哪里?只好参照了这篇博客的写法,然后就1A了,表示很无语呀!该题主要是两个方面的处理,对字符串的处理上,如何把关键词抠出来。然后对这些关键词进行建图处理,再对每一次询问的时候进行搜索两个关键词之间是否存在路径,如果有则说明关系存在,反之亦然。详见code。

        题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4096

       code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;

const int MAXN = 200+10;
const int M = 1e5+100;
int t,cas,cnt,u,v;
map<string,int> nou;
map<string,int> ver;
int head[MAXN*2],vis[MAXN*2],eid;
char str[M],s1[MAXN],s2[MAXN],s3[MAXN],s4[MAXN],s5[MAXN],s6[MAXN];

struct Edge{
    int v,next;
}e[MAXN*MAXN*2];

void addedge(int u,int v){ //建图
    e[eid].v=v;
    e[eid].next=head[u];
    head[u]=eid++;
}

bool dfs(int u,int v){ //路径搜索
    vis[u]=1;
    if(u==v) return true;
    for(int i=head[u];i!=-1;i=e[i].next){
        if(!vis[e[i].v])
            if(dfs(e[i].v,v))
                return true;
    }
    return false;
}

int main(){
    //freopen("input.txt","r",stdin);
    cas=0;
    scanf("%d",&t);
    getchar();
    while(t--){
        printf("Case #%d:\n",++cas);
        cnt=0;eid=0;
        nou.clear();ver.clear();
        memset(head,-1,sizeof(head));
        while(gets(str)){//cin.getline(str,2000,'\n'),这里使用gets的时间更快
            int len=strlen(str);
            if(str[len-1]=='!'){ //结束判断
                printf("\n");
                break;
            }
            int num=sscanf(str,"%s %s %s %s %s %s",s1,s2,s3,s4,s5,s6); //接收每一个单词
            if(num==3){ //如果句子长度为3
                len=strlen(s3);
                if(s3[len-1]=='.'){ //如果为陈述句
                    s3[len-1]='\0';
                    if(s2[0]=='a'){ //关键词为are,表示关键词为名词
                        if(!nou[s1]) nou[s1]=++cnt;
                        if(!nou[s3]) nou[s3]=++cnt;
                        u=nou[s1];
                        v=nou[s3];
                    }
                    else{  //关键词为can,表示关键词为名词+动词
                        if(!nou[s1]) nou[s1]=++cnt;
                        if(!ver[s3]) ver[s3]=++cnt;
                        u=nou[s1];
                        v=ver[s3];
                    }
                    addedge(u,v); //增加有向边
                }
                else{  //如果为疑问句
                    s3[len-1]='\0';
                    if(s1[0]=='a'){  //关键词为are,表示关键词为名词
                        if(!nou[s2]) nou[s2]=++cnt;
                        if(!nou[s3]) nou[s3]=++cnt;
                        u=nou[s2];
                        v=nou[s3];
                    }
                    else{  //关键词为can,表示关键词为名词+动词
                        if(!nou[s2]) nou[s2]=++cnt;
                        if(!ver[s3]) ver[s3]=++cnt;
                        u=nou[s2];
                        v=ver[s3];
                    }
                    memset(vis,0,sizeof(vis)); //初始化访问数组
                    if(dfs(u,v)) printf("Y"); //进行路径搜索
                    else printf("M");
                }
            }
            else{ //如果句子长度为6,与长度为3的判断方法一致
                len=strlen(s6);
                if(s6[len-1]=='.'){
                    s6[len-1]='\0';
                    if(s5[0]=='a'){
                        if(!ver[s4]) ver[s4]=++cnt;
                        if(!nou[s6]) nou[s6]=++cnt;
                        u=ver[s4];
                        v=nou[s6];
                    }
                    else{
                        if(!ver[s4]) ver[s4]=++cnt;
                        if(!ver[s6]) ver[s6]=++cnt;
                        u=ver[s4];
                        v=ver[s6];
                    }
                    addedge(u,v);
                }
                else{
                    s6[len-1]='\0';
                    if(s1[0]=='a'){
                        if(!ver[s5]) ver[s5]=++cnt;
                        if(!nou[s6]) nou[s6]=++cnt;
                        u=ver[s5];
                        v=nou[s6];
                    }
                    else{
                        if(!ver[s5]) ver[s5]=++cnt;
                        if(!ver[s6]) ver[s6]=++cnt;
                        u=ver[s5];
                        v=ver[s6];
                    }
                    memset(vis,0,sizeof(vis));
                    if(dfs(u,v)) printf("Y");
                    else printf("M");
                }
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值