codeforces 149E Martian Strings
2016-01-12 16:39
302 查看
正着建一个反着建一个后缀自动机,然后直接向下走,记录从前面往后面,以及从后面往前面
匹配i位时在原串的最小位置,然后枚举端点再判断
匹配i位时在原串的最小位置,然后枚举端点再判断
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; #define N 100010 #define INF 1000000000 int n,Ws ,Place[110] ,Place1[110] ; char S ,S1[110] ; struct SAM{ SAM *fa,*son[26]; int val,R; void S_clear(){ fa=0;val=0;R=INF; memset(son,0,sizeof(son)); } }*last,*root,State[N*2],*tot,*pos[N*2]; void Init() { tot=State;root=last=tot++; root->S_clear(); } void Insert(int w) { SAM *p=last,*np=tot++;np->S_clear(); np->val=p->val+1;np->R=np->val; while(p&&!p->son[w]) p->son[w]=np,p=p->fa; if(p==0) np->fa=root; else { SAM *q=p->son[w]; if(p->val+1==q->val) np->fa=q; else { SAM *nq=tot++;nq->S_clear(); memcpy(nq->son,q->son,sizeof(q->son)); nq->val=p->val+1; nq->fa=q->fa;q->fa=nq;np->fa=nq; while(p&&p->son[w]==q) p->son[w]=nq,p=p->fa; } } last=np; } int main() { scanf("%s",S); n=(int)strlen(S); Init(); for(int i=0;i<n;i++) Insert(S[i]-'A'); int qwer=(int)(tot-State); for(SAM *p=State;p!=tot;p++) Ws[p->val]++; for(int i=1;i<=n;i++) Ws[i]+=Ws[i-1]; for(SAM *p=State;p!=tot;p++) pos[--Ws[p->val]]=p; for(int i=qwer-1;i>=0;i--) { SAM *p=pos[i]; if(p->fa) p->fa->R=min(p->fa->R,p->R); } for(int i=0;i<=109;i++) for(int j=0;j<N;j++) Place[i][j]=INF; int m;scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",S1[i]); int len=(int)strlen(S1[i]); SAM *p=root;int L=0; Place[i][0]=0; for(int j=0;j<len;j++) { int num=S1[i][j]-'A'; if(p->son[num]) { L++; p=p->son[num]; } else break; Place[i][L]=min(Place[i][L],p->R); } } Init(); for(int i=n-1;i>=0;i--) Insert(S[i]-'A'); qwer=(int)(tot-State); memset(Ws,0,sizeof(Ws)); memset(pos,0,sizeof(pos)); for(SAM *p=State;p!=tot;p++) Ws[p->val]++; for(int i=1;i<=n;i++) Ws[i]+=Ws[i-1]; for(SAM *p=State;p!=tot;p++) pos[--Ws[p->val]]=p; for(int i=qwer-1;i>=0;i--) { SAM *p=pos[i]; if(p->fa) p->fa->R=min(p->fa->R,p->R); } for(int i=0;i<=109;i++) for(int j=0;j<N;j++) Place1[i][j]=INF; for(int i=1;i<=m;i++) { int len=(int)strlen(S1[i]); SAM *p=root;int L=0; Place1[i][0]=0; for(int j=len-1;j>=0;j--) { int num=S1[i][j]-'A'; if(p->son[num]) { L++; p=p->son[num]; } else break; Place1[i][L]=min(Place1[i][L],p->R); } } int Ans=0; for(int i=1;i<=m;i++) { int len=(int)strlen(S1[i]); for(int j=1;j<len;j++) { if(Place[i][j]+Place1[i][len-j]<=n) { Ans++; break; } } } cout<<Ans<<endl; return 0; }
相关文章推荐
- 鼠标画上去图片旋转360度
- 【主席树】BZOJ 3207 花神的嘲讽计划Ⅰ
- Netty4版本升级血泪史之线程篇
- iOS界面跳转方式
- 使用postman做接口测试
- VMware下安装rhci-5.8-1
- NHibernate的简单例子
- TCP拥塞控制
- <iOS>XML解析
- iOS拍照后存储照片到相册中
- linux下安装awk
- javax.net.ssl.SSLHandshakeException的解决方法
- font-face跨域办法
- 华为机试——回文数判断
- html5图片上传与预览实现
- 常用Java 加密算法
- ORA-29275: partial multibyte character
- MATLAB实现将图像转换为素描(简笔画)风格
- Linux C - [2] - 之 编译 helloworld
- 论Hander机制