HDU 5507 GT and strings 字符串相关暴力

GT and strings

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 277    Accepted Submission(s): 52


Problem Description
You are given  N  strings.Their total length is  L .

There are  Q  questions.

For each question please work out two tasks:

①whether  Sx  is a subsequence of  Sy .

②whether  Sx  is a substring of  Sy .

If the statement is true print  1 ,otherwise print  0
 

Input
In the first line there is the testcase  T .

For each teatcase:

In the first line there are two numbers  N  and  Q .

In the next  N  lines there are  N  strings  i -th line is a string standing for  Si .

**Note that  Si  consists of only lower alphabets.**

In the last  Q  lines there are two numbers (x,y) .

T5 N,L,Q100000 。Every string's length is at least  1

There are  60%  testcases that  L100 Q1000

You'd better print the enter in the last line when you hack others.

You'd better not print space in the last of each line when you hack others.
 

Output
For each testcase,print only one lines.

It's a string contains only  0  and  1  and its length is  Q2 .

i21 -th character is the answer of the  i -th question of ①,

and  i2 -th character is the answer of the  i -th question of ②。
 

Sample Input
  
  
1 6 6 orz stilwell skydec se dec orz 1 2 1 3 1 6 4 1 4 2 6 1
 

Sample Output
  
  
000011001011
 

Source
 
------------------------------------------------------------------------------------------------------------------------------------------------------------

题意:给n个字符串和q个询问,询问会给出两个数字x,y,问:1.x串是否是y串的子序列,2.x串是否是y串的子串。对于每个询问,输出两个字符,第一个为‘1’代表第一个询问正确,为‘0’代表第一个询问错误,第二个字符同理。

思路:必须说明这题数据有问题,题意就没有说清数据的范围,因此时间复杂度的估计没什么意义,并且自己也看了别人的代码才知道的数组开多大……总之做法就是比较暴力的做法,
对于第一种询问:先预处理,dp[i][j]代表字符串中第i个字符的后面字符中(包括它自己)'a'+j这个字符的位置,处理每个询问,用x字符串来走y字符串的dp数组,走完后的最后位置还在y里面的话就是‘1’,反之就是‘0’
对于第二种询问:子串问题很容易想到ac自动机,每个串insert的时候,给每个是串的结尾的节点一个编号,并每个串对应的编号记为jiedian[i]代表第i个串结尾在自动机的位置的节点编号(原谅我的尴尬英语……写的时候没注意,写好也不想因为这种问题去改了),拿所有y串走一遍ac自动机,因为问的是x是否为y的子串,则y串走ac自动机的时候一定会走到x串对应的结尾节点的,用map< pair< int , int >  bool >标记为map[make_pair(走到的节点编号,y串的节点编号)]=true(用set < pair< int , int >  bool >也完全没问题)。最后对于每个询问,看make_pair(x串的节点编号,y串的节点编号)的标记,即可知道询问答案。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
#define MS(x,y) memset(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
typedef pair<int,int> P;
const int MAXN=1e5+5;
const int INF=0x3f3f3f3f;

char str[MAXN];
int pos[MAXN],ans[MAXN][2],query[MAXN][2];
int dp[MAXN][26];
bool isqu[MAXN];
int T,n,m;

void solve1(){
    for(int i=0;i<26;++i) dp[pos[n]][i]=INF;
    for(int i=pos[n]-1;i>=0;--i){
        for(int j=0;j<26;++j) dp[i][j]=dp[i+1][j];
        dp[i][str[i]-'a']=i;
    }
    for(int i=0;i<m;++i){
        int u=query[i][0],v=query[i][1];
        if(pos[u]-pos[u-1]>pos[v]-pos[v-1]){
            ans[i][0]=0;
            continue;
        }
        int point=pos[v-1];
        bool flag=false;
        for(int j=pos[u-1];j<pos[u];++j){
            point=dp[point][str[j]-'a'];
            if(point>=pos[v]){
                flag=true;
                break;
            }
            ++point;
        }
        if(flag) ans[i][0]=0;
        else ans[i][0]=1;
    }
}
//int DP(int x,int y){
//    int gui=pos[x-1],i=pos[y-1];
//    if(pos[x]-pos[x-1]>pos[y]-pos[y-1]) return 0;
//    while(gui<pos[x]){
//        int tt=str[gui]-'a';
//        if(dp[i][tt]>=pos[y]) return 0;
//        gui++;
//        i=dp[i][tt];++i;
//    }
//    return 1;
//}
//void solve1(){
//    for(int i=0;i<26;++i) dp[pos[n]][i]=INF;
//    for(int j=pos[n]-1;j>=pos[0];--j){
//        for(int k=0;k<26;++k)
//            if(str[j]-'a'==k) dp[j][k]=j;
//            else dp[j][k]=dp[j+1][k];
//    }
//    for(int i=0;i<m;++i)
//        ans[i][0]=DP(query[i][0],query[i][1]);
//}

struct Tire{
    int nxt[MAXN][26],fail[MAXN],cnt[MAXN],jiedian[MAXN];
    int L,id;
    map<P,bool> mp;
    
//    int node(){
//        for(int i=0;i<26;++i) nxt[L][i]=-1;
//        cnt[L]=0;
//        return L++;
//    }
    void init(){
        mp.clear();
        id=L=0;
        MS(fail,0);
        MS(nxt,0);
        MS(cnt,0);
    }
    void insert(int x){
        int now=0;
        for(int i=pos[x-1];i<pos[x];++i){
            if(nxt[now][str[i]-'a']==0)
                nxt[now][str[i]-'a']=++L;
            now=nxt[now][str[i]-'a'];
        }
        if(!cnt[now]) cnt[now]=++id;
        jiedian[x]=cnt[now];
    }
    void build(){
        queue<int> Q;
        for(int i=0;i<26;++i){
            if(nxt[0][i]) Q.push(nxt[0][i]);
        }
        while(!Q.empty()){
            int t1=Q.front();Q.pop();
            for(int i=0;i<26;++i){
                int t2=nxt[t1][i];
                if(t2){
                    Q.push(t2);
                    int t3=fail[t1];
                    while(t3&&!nxt[t3][i]) t3=fail[t3];
                    fail[t2]=nxt[t3][i];
                }
            }
        }
    }
    
    void find(int y){
        int now=0;
        for(int i=pos[y-1];i<pos[y];++i){
            now=nxt[now][str[i]-'a'];
            for(int p=now;p;p=fail[p]){
                if(cnt[p]){
                    mp[MP(cnt[p],jiedian[y])]=true;
                }
                else{
                    if(fail[p]&&!cnt[fail[p]])
                        fail[p]=fail[fail[p]];
                }
            }
        }
    }
    void solve(){
        init();
        for(int i=1;i<=n;++i){
            insert(i);
        }
        build();
        for(int i=1;i<=n;++i)
            if(isqu[i]) find(i);
        for(int i=0;i<m;++i)
            ans[i][1]=mp[MP(jiedian[query[i][0]],jiedian[query[i][1]])];
    }
}ac;

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%s",str+pos[i-1]);
            pos[i]=strlen(str);
        }
        MS(isqu,false);
        for(int i=0;i<m;++i){
            scanf("%d%d",&query[i][0],&query[i][1]);
            isqu[query[i][1]]=true;
        }
        solve1();
        ac.solve();
        for(int i=0;i<m;++i) printf("%d%d",ans[i][0],ans[i][1]);
        putchar(10);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值