标签:blog http io ar for sp div on art
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5069
题意:给出n个串,m个询问,每个询问(u,v),求u的一个最长后缀是v的前缀。
思路:离线。将关于u的后缀的查询放在一起,然后将u插入后缀自动机。对于每个v跑一遍即可。
struct SAM
{
SAM *son[4],*pre;
int len;
int ok;
void init()
{
clr(son,0);
pre=0;
ok=0;
}
};
SAM sam[N],*head,*last;
int cnt;
void initSam()
{
head=last=&sam[0];
head->init();
cnt=1;
}
int get(char x)
{
if(x==‘A‘) return 0;
if(x==‘T‘) return 1;
if(x==‘G‘) return 2;
return 3;
}
void insert(int x)
{
SAM *p=&sam[cnt++],*u=last;
p->init();
p->len=last->len+1;
last=p;
for(;u&&!u->son[x];u=u->pre) u->son[x]=p;
if(!u) p->pre=head;
else if(u->son[x]->len==u->len+1) p->pre=u->son[x];
else
{
SAM *r=&sam[cnt++],*q=u->son[x];
*r=*q; r->len=u->len+1;
p->pre=q->pre=r;
for(;u&&u->son[x]==q;u=u->pre) u->son[x]=r;
}
}
char s[N*2];
int cur;
int start[N],len[N];
vector<pair<int,int> > V[N];
int ans[N];
map<int,int> mp;
int n,m;
int main()
{
// FFF;
while(scanf("%d%d",&n,&m)!=-1)
{
cur=0;
int i;
for(i=1;i<=n;i++)
{
scanf("%s",s+cur);
start[i]=cur;
len[i]=strlen(s+cur);
cur+=len[i]+3;
}
for(i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
V[u].pb(MP(v,i));
}
for(i=1;i<=n;i++) if(SZ(V[i])>0)
{
int j;
initSam();
for(j=start[i];s[j];j++) insert(get(s[j]));
SAM *p=last;
while(p!=NULL) p->ok=1,p=p->pre;
mp.clear();
for(j=0;j<SZ(V[i]);j++)
{
int k=V[i][j].first;
int id=V[i][j].second;
if(mp.count(k))
{
ans[id]=mp[k];
continue;
}
SAM *p=head;
int t,tmp=0,cur=0;
for(t=start[k];s[t];t++)
{
int x=get(s[t]);
if(p->son[x])
{
cur++;
p=p->son[x];
if(p->ok) tmp=max(tmp,cur);
}
else break;
}
mp[k]=tmp;
ans[id]=tmp;
}
V[i].clear();
}
for(i=1;i<=m;i++) printf("%d\n",ans[i]);
}
}
HDU 5056 Harry And Biological Teacher
标签:blog http io ar for sp div on art
原文地址:http://www.cnblogs.com/jianglangcaijin/p/4034017.html