【GDOI2017 day1】微信
来源:互联网 发布:股票盈亏记录软件 编辑:程序博客网 时间:2024/06/05 10:37
Description
Solution
这道题目很容易就可以看出来需要求某几个trie上的最长公共子串,如果我们把trie建出来之后可以发现,目前需要克服的困难是多个串一起求lcp。
对于这个问题,我们可以把所有trie都合并在一起,对于每一个节点记录一下分别是哪些天出现过的,之后在这个trie上建一个后缀自动机。我们如何利用这个建出的自动机呢?可以发现,对于每一个节点我们都有一个状态标记,因为遍历自动机可以求出所有子串,那么只要判断当前串被哪些天包含就可以了。设一个
Code
#include<iostream> #include<string.h>#include<math.h>#include<stdio.h>#include<algorithm>using namespace std;#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)const int N=1e6+5,MX=(1<<20)+5;struct nod1{ int son[26],fa,len,s;}t[N*2];struct nod2{ int son[26],s,fa;}tr[N*2];struct arr{ int x,len;}a[N*2];char s[N];int c[N],D[N*2],la[N*2],cen[N],F[MX],L[N*2],las[N*2];int n,Q,i,j,len,sum,num,p,np,q,nq,father,next;bool bz,B[N*2];bool cmp(arr x,arr y){return x.len>y.len;}void add(int c,int &last,int S){ p=last,np=++sum;last=sum; t[np].len=t[p].len+1;/**/t[np].s=S;/**/ while(p&&!t[p].son[c]) t[p].son[c]=np,p=t[p].fa; if(!p) t[np].fa=1; else{ q=t[p].son[c]; if(t[p].len+1==t[q].len) t[np].fa=q; else{ t[nq=++sum]=t[q],t[nq].len=t[p].len+1;/**/t[nq].s=S;/**/ t[np].fa=t[q].fa=nq; while(p&&t[p].son[c]==q) t[p].son[c]=nq,p=t[p].fa; } }}void trie(int now,int Day){ int i,x,y; x=cen[now];now++; if(!tr[x].son[c[now]]) tr[x].son[c[now]]=++sum,tr[sum].fa=x; y=tr[x].son[c[now]]; tr[y].s=(tr[y].s|Day); cen[now]=y;}void deal(){ int i,x,y,l=0,r=1; D[1]=1; while(l<r){ x=D[++l]; fo(i,0,25) if(tr[x].son[i]){ y=tr[x].son[i]; las[y]=las[x]; add(i,las[y],tr[y].s); D[++r]=y; } } fo(i,1,sum) a[i]=(arr){i,t[i].len}; sort(a+1,a+sum+1,cmp); fo(i,1,sum){ x=a[i].x,y=t[x].fa,t[y].s=(t[y].s|t[x].s); F[t[x].s]=(F[t[x].s]>t[x].len)?F[t[x].s]:t[x].len; }}int main(){ freopen("wechat.in","r",stdin); freopen("wechat.out","w",stdout); sum=cen[0]=1; scanf("%d",&n); fo(i,1,n){ scanf("%s",s+1);len=strlen(s+1);num=0; fo(j,1,len) if(s[j]!='<'){ c[++num]=s[j]-'a'; trie(num-1,1<<(i-1)); }else num--; } sum=next=las[1]=1; deal(); fd(i,(1<<n)-1,0) fo(j,0,n-1) if(i&(1<<j)) F[i^(1<<j)]=max(F[i^(1<<j)],F[i]); scanf("%d",&Q); fo(i,1,Q){ scanf("%s",s+1);len=strlen(s+1); num=0; while(len) num=num*2+s[len]-'0',len--; printf("%d\n",F[num]); }}
阅读全文
0 0
- 【GDOI2017 day1】微信
- 【GDOI2017 day1】微信
- 【GDOI2017 day1】微信
- 【JZOJ5098】【GDOI2017 day1】微信
- 【jzoj5098】【GDOI2017 day1】【微信】【tire上建sam】
- 【GDOI2017 day1 T3】微信 && SAM学习小记
- 【GDOI2017 day1】取石子游戏
- 【JZOJ5096】【GDOI2017 day1】房屋购置
- 【GDOI2017第二轮模拟day1】最长路径
- 【GDOI2017第二轮模拟day1】公路建设
- 【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设
- [JZOJ5073]【GDOI2017第三轮模拟day1】影魔
- 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔
- 【GDOI2017第四轮模拟day1】数列
- 【GDOI2017第四轮模拟day1】数列
- 【JZOJ5097】【GDOI2017 day1】取石子游戏
- {题解}[jzoj5097]【GDOI2017 day1】取石子游戏
- 微信公众号开发day1
- 购买公司股票 = 变相降薪?
- elasticsearch学习笔记(三)
- OkHttp中的线程安全问题
- Buy a Hat
- 仿建行轮盘按键
- 【GDOI2017 day1】微信
- Vue基础之表单控件绑定
- python3实战scrapy生成csv文件
- 如何在vs2013中搭建python环境
- HTML 表单用于搜集不同类型的用户输入
- 类的构造函数初探
- ORACLE多表关联UPDATE 语句
- ObjectARX编程(六) ------块和属性
- 第二十一天H5进阶