神牛的养成计划---可持久化trie
来源:互联网 发布:冠能狗粮网络代理 编辑:程序博客网 时间:2024/05/29 14:40
题目大意
给定n个由小写字母组成的字符串。现在有m个询问,每个询问指定两个字符串s1,s2.要求回答:在给定的n个字符串中,有多少个字符串s满足:s1是s的前缀且s2是s的后缀。强制在线!
数据范围
限制
时间限制:1s
空间限制:256M (512M) (原题限制256M,这个太丧心病狂了!作为蒟蒻,我只会写512M限制的!)
题解
对给定的n个字符串建一棵字典树.对于询问,我们先在trie上匹配,假设最后停在了p节点,那么所有满足条件的字符串s的末尾节点一定是在p的子树中的。如果我们把原字符串按照字典序排序(其实就是trie的dfs序),那么满足条件的s所对应的编号一定落在某个连续区间内。于是我们用可持久化trie维护后缀就好了。
第一次写可持久化trie,感觉还算比较好写。
看别人的题解,都是自定义cmp函数,然后sort一下。只有我蠢蠢地按dfs序排序。
代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define MAXN 2000100 char s[MAXN],t[MAXN]; int _l[MAXN],_r[MAXN]; int n,m,tot=1; int to[MAXN][26],rt[MAXN],nxt[MAXN][26],summ[MAXN],mn[MAXN],mx[MAXN],order[MAXN]; int C[MAXN]; vector<int>P[MAXN]; void ins(int id) { int x,p=1; for(int i=0;t[i]!='\0';i++) { x=t[i]-'a'; if(!to[p][x]) { to[p][x]=++tot; } p=to[p][x]; } P[p].push_back(id); return ; } int tim=0; const int inf=0x3c3c3c3c; void dfs(int p) { mn[p]=inf; mx[p]=0; for(int i=0;i<P[p].size();i++) { order[P[p][i]]=++tim; mn[p]=min(mn[p],tim); mx[p]=max(mx[p],tim); } for(int i=0;i<26;i++) { if(to[p][i]) { dfs(to[p][i]); mn[p]=min(mn[p],mn[to[p][i]]); mx[p]=max(mx[p],mx[to[p][i]]); } } return ; } bool cmp(int a,int b) { return order[a]<order[b]; } void ins2(int& p,int f,int d,int pp) { p=++tot; summ[p]=summ[f]+1; memcpy(nxt[p],nxt[f],sizeof(nxt[f])); if(d>pp) { ins2(nxt[p][s[d]-'a'],nxt[f][s[d]-'a'],d-1,pp); } return ; } int lstans=0; int main() { scanf("%d",&n); for(int i=1,tmp;i<=n;i++) { scanf("%s",t); _l[i]=_r[i-1]+1; tmp=strlen(t); _r[i]=_l[i]+tmp-1; for(int j=0;j<tmp;j++) { s[_l[i]+j]=t[j]; } C[i]=i; ins(i); } dfs(1); sort(C+1,C+1+n,cmp); tot=1; for(int i=1,I;i<=n;i++) { I=C[i]; ins2(rt[i],rt[i-1],_r[I],_l[I]); } int L,R; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",t); L=inf; R=0; int x=1; for(int c,j=0;t[j]!='\0';j++) { c=t[j]-'a'; c=c+lstans; c%=26;//这个傻逼错误,我调了半天才发现!!c-=c>=26?26:0; x=to[x][c]; } if(x) { L=mn[x]; R=mx[x]; } scanf("%s",t); if(L>R) { lstans=0; } else { int x=rt[L-1],y=rt[R],c,nn=strlen(t); for(int j=nn-1;j>=0;j--) { c=t[j]-'a'; c=c+lstans; c%=26;//c-=c>=26?26:0; x=nxt[x][c]; y=nxt[y][c]; } lstans=summ[y]-summ[x]; } printf("%d\n",lstans); } return 0; }
阅读全文
0 0
- 神牛的养成计划---可持久化trie
- bzoj 4212: 神牛的养成计划 (trie+可持久化trie)
- [BZOJ4212]神牛的养成计划(trie+可持久化trie)
- 可持久化trie
- [BZOJ3261]-可持久化trie
- bzoj 2741 分块 + 可持久化trie
- hdu 4757 Tree(可持久化Trie)
- 3166: [Heoi2013]Alo 可持久化trie
- HDU-5801 可持久化Trie树
- HDU 4757 可持久化trie树
- BZOJ3166 [Heoi2013]Alo 可持久化Trie
- BZOJ 3166 可持久化Trie
- 可持久化01Trie [Heoi2013]Alo
- 4212: 神牛的养成计划
- BZOJ 3207 花神的嘲讽计划I Hash+可持久化线段树/划分树
- BZOJ 3207 花神的嘲讽计划Ⅰ Hash+可持久化线段树
- 【BZOJ3207】花神的嘲讽计划Ⅰ hash+可持久化线段树
- BZOJ 3207 花神的嘲讽计划Ⅰ 可持久化线段树
- Java开发工具日常设置汇总
- 小问题 记录
- 解决窗口刷新闪烁
- 我的第一篇博客
- 牛客网javascript读取输入
- 神牛的养成计划---可持久化trie
- 自动化测试中对Alert, 多窗口,下拉框的处理
- dedecms基础2012
- 安装appium
- USACO-Section1.3 Combination Lock[其他]
- java Spring定时任务详解
- 属性操作
- LogSegment分析
- MVC,MVP 和 MVVM 的图示