您的位置:首页 > 其它

codeforces 149E Martian Strings

2016-01-12 16:39 302 查看
正着建一个反着建一个后缀自动机,然后直接向下走,记录从前面往后面,以及从后面往前面

匹配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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: