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. [转帖]docker容器保持运行不退出

    docker容器保持运行不退出 2019年01月20日 23:21:22 chvalrous 阅读数 1511   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  2. Oracle导入/导出某个用户下的数据库

    导出 exp用户名/密码@数据库实例owner=用户名file=文件存储路径 例如:exp MM/123456@ORCL owner=MM file=F\abcd.dmp 导入 imp用户名/密码@数 ...

  3. PAT A1020 Tree Traversals(25)

    题目描述 Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder ...

  4. centos7 使用nginx + tornado + supervisor搭建服务

    如何在Linux下部署一个简单的基于Nginx+Tornado+Supervisor的Python web服务. Tornado:官方介绍,是使用Python编写出来的一个极轻量级.高可伸缩性和非阻塞 ...

  5. django channels

    django channels django channels 是django支持websocket的一个模块. 1. 安装 `pip3 install channels` 2. 快速上手 2.1 在 ...

  6. HTML 标签的 for 属性

    HTML 标签的 for 属性 for 属性规定 label 与哪个表单元素绑定. 隐式和显式的联系 label通常以下面两种方式中的一种来和表单控件相联系: 将表单控件作为标记标签的内容,这样的就是 ...

  7. js排列组合

    /* 全排列主要用到的是递归和数组的插入 arr: 需要排列的数组 第一步:从里面取一个,创建一个新的数组,形式为二维,例如arr = [1,2,3]; 取出3(没有特殊要求,随便取一个),放入 te ...

  8. Aveva Marine 新建项目001

    1# 项目代号定义,三个字符,例如Abc 2# 新建文件夹,命名为“Abc” 3# 新建文件名为evars.bat文件,放到项目文件夹的根目录 内容为: SET Abc000=项目文件夹路径\Abc0 ...

  9. shiro学习(三,shiro加密)

    shiro加密 使用MD5加密  认证 //自定义的Realm 域 public class CustomRealmSecret extends AuthorizingRealm { @Overrid ...

  10. 深入探讨java的类加载器

    类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...