OvO http://acm.hdu.edu.cn/showproblem.php?pid=6096

  ( 2017 Multi-University Training Contest - Team 6 - 1001)

  对于n个串,构造新串。(构造方法:例如若串为ABCDE,构造新串为AEBDCCDBEA)、

  将新串插入到字典树(字典树每个节点存放一个vector)中,对于每个新串遍历到的节点,将原串的长度长度放入这些节点的vector中、

  将字典树每个节点的vector从小到大排序。

  对于询问的前后缀,类似地构造新串,空余出补*,(例如前缀ABC,后缀DEFGH,构造新串为AHBGCF*E*D)

  然后对于这些新串在字典树中进行询问,对于每个匹配到的节点,合法串的数量就是vector中保存的长度大于等于前缀后缀长度和的数字的数量。

  (思路来源于某大佬

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue> using namespace std; const int M=5e5+44;
const int N=1e5+44; struct Node
{
int len,pos;
}; queue<Node> que; struct Trie
{
const static int TRIE_M=1204000;
const static int CHAR_SIZE=26; int root,tol,ch[TRIE_M][27];
vector<int> tree[TRIE_M]; int newnode()
{
tree[tol].clear();
for(int i=0;i<26;i++)
ch[tol][i]=-1;
return tol++;
} void init()
{
tol=0;
root=newnode();
} void insert(char strtmp[],int lentmp)
{
// cout<<"strtmp: "<<strtmp<<endl;
int i,j;
int now=root,nxt,valtmp;
for(i=0;i<lentmp;i++)
{
valtmp=strtmp[i]-'a';
if(ch[now][valtmp]==-1)
ch[now][valtmp]=newnode();
now=ch[now][valtmp];
tree[now].push_back(lentmp/2);
// cout<<"now: "<<now<<" tree[now] size: "<<tree[now].size()<<endl;
}
} void build()
{
for(int i=0;i<tol;i++)
sort(tree[i].begin(),tree[i].end());
} int getval(int pos,int xlen)
{
int li=-1,ri=tree[pos].size(),mid;
// cout<<"getval pos:"<<pos<<' '<<" size: "<<tree[pos].size()<<endl;
// cout<<"detail val:"<<tree[pos][0]<<' '<<tree[pos][1]<<endl;
while(li<ri-1)
{
mid=(li+ri)>>1;
if(tree[pos][mid]<xlen)
li=mid;
else ri=mid;
}
// cout<<"li: "<<li<<endl;
return tree[pos].size()-(li+1);
} int query(char strtmp[],int lentmp,int xlen)
{
char chrtmp;
int i,j,ret=0,pos,nxt;
Node q,qq;
while(!que.empty())
que.pop();
q.len=0; q.pos=0;
que.push(q);
while(!que.empty())
{
q=que.front(); que.pop();
chrtmp=strtmp[q.len];
pos=q.pos;
// cout<<chrtmp<<' '<<pos;
// if(chrtmp!='*')
// cout<<" ch[pos][chrtmp-'a']= "<<ch[pos][chrtmp-'a'];
// cout<<endl;
if(chrtmp=='*')
for(i=0;i<26;i++)
{
nxt=ch[pos][i];
if(nxt!=-1)
{
qq.len=q.len+1;
qq.pos=nxt;
if(qq.len==lentmp)
ret+=getval(qq.pos,xlen);
else que.push(qq);
}
}
else
{
nxt=ch[pos][chrtmp-'a'];
if(nxt!=-1)
{
qq.len=q.len+1;
qq.pos=nxt;
if(qq.len==lentmp)
ret+=getval(qq.pos,xlen);
else que.push(qq);
}
}
}
return ret;
}
} trie; int n,q;
char strtmp[M],pretmp[M],suftmp[M],strget[M]; int main()
{
// freopen("数据\\1001.in","r",stdin);
// freopen("数据\\fxxl1001.out","w",stdout);
int lentmp,prelen,suflen;
int cas,i,j,ans;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&q);
trie.init();
for(i=1;i<=n;i++)
{
scanf("%s",strtmp);
lentmp=strlen(strtmp);
for(j=0;j<lentmp;j++)
{
strget[j*2]=strtmp[j];
strget[j*2+1]=strtmp[lentmp-1-j];
}
trie.insert(strget,lentmp*2);
}
trie.build();
for(i=1;i<=q;i++)
{
scanf("%s%s",pretmp,suftmp);
reverse(suftmp,suftmp+strlen(suftmp));
prelen=strlen(pretmp); suflen=strlen(suftmp);
lentmp=max(prelen,suflen);
for(j=0;j<lentmp;j++)
{
if(j<prelen)
strget[j*2]=pretmp[j];
else strget[j*2]='*';
if(j<suflen)
strget[j*2+1]=suftmp[j];
else strget[j*2+1]='*';
}
lentmp*=2;
if(strget[lentmp-1]=='*') lentmp--;
ans=trie.query(strget,lentmp,prelen+suflen);
printf("%d\n",ans);
}
}
return 0;
} /* 1
4 1
aaaa
aaaaa
aaaaa
aa
aa aa */

  

hdu 6096 String的更多相关文章

  1. 2017多校第6场 HDU 6096 String AC自动机

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096 题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数. 解法: ...

  2. HDU 6096 String(AC自动机+树状数组)

    题意 给定 \(n\) 个单词,\(q\) 个询问,每个询问包含两个串 \(s_1,s_2\),询问有多少个单词以 \(s_1\) 为前缀, \(s_2\) 为后缀,前后缀不能重叠. \(1 \leq ...

  3. HDU 6096 String (AC自动机)

    题目链接 Problem Description Bob has a dictionary with N words in it. Now there is a list of words in wh ...

  4. 2017ACM暑期多校联合训练 - Team 6 1001 HDU 6096 String (字符串处理 字典树)

    题目链接 Problem Description Bob has a dictionary with N words in it. Now there is a list of words in wh ...

  5. HDU 6096 String (AC自动机)

    题意:给出n个字符串和q个询问,每次询问给出两个串 p 和 s .要求统计所有字符串中前缀为 p 且后缀为 s (不可重叠)的字符串的数量. 析:真是觉得没有思路啊,看了官方题解,真是好复杂. 假设原 ...

  6. HDU 6096 String 排序 + 线段树 + 扫描线

    String Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Problem De ...

  7. HDU 3374 String Problem (KMP+最大最小表示)

    HDU 3374 String Problem (KMP+最大最小表示) String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory ...

  8. HDU - 6096 :String (AC自动机,已知前后缀,匹配单词,弱数据)

    Bob has a dictionary with N words in it. Now there is a list of words in which the middle part of th ...

  9. HDU 3374 String Problem(KMP+最大/最小表示)

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

随机推荐

  1. Linux系列(2):入门之线上求助

    前言:Linux命令那么多,你是否为记不住Linux的命令而烦恼呢? 这一章节就是来解决这个问题的. 1.Linux系统的线上求助 1.指令补全 在上一章节提到过使用[Tab]快捷键可以根据用户输入的 ...

  2. springboot系列:使用缓存

    前言:springboot已经为我们实现了抽象的api接口,因此当我们使用不同的缓存时,只是配置有可能有点区别(比如ehcache和Redis),但是在程序中使用缓存的方法是一样的. 1.spring ...

  3. linux环境下Python搭建

    安装gcc   yum install gcc 安装zlib   yum -y install zlib* 安装openssl-devel   yum install openssl-devel -y ...

  4. T100 事务的开始与结束

    例如: IF cl_ask_confirm('apm-00801') THEN CALL s_transaction_begin() IF NOT axmt500_change_xmdc015('u' ...

  5. Dom编程-左侧菜单栏设计模型实现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. python函数篇0-1

    创建类和对象 面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用. 类就是一个模板,模板里可以包含多个函数, ...

  7. 区间dp 整数划分问题

    整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...

  8. c#操作word书签

    因项目需要,给word文档的书签赋值,框架没有相关内容,于是自己上网加上查看文档,成功搞定该功能.下面是我的实现过程: 首先需要引用nuget包: Microsoft.Office.Interop.W ...

  9. Navicat连接CentOS7中的MariaDB

    Step 1:首先登录数据库设置开启远程连接 mysql -u root -p Step 2:使用改表法实现远程连接 use mysql; update user set host = '%' whe ...

  10. [转载]Yacc基础

    原文:https://www.ibm.com/developerworks/cn/linux/sdk/lex/index.html,摘录部分内容. Yacc的定义 Yacc 代表 Yet Anothe ...