您的位置:首页 > 其它

【SDOI2016】bzoj4516 生成魔咒【解法一】

2017-04-28 18:00 260 查看
每次在SAM中加入一个字符,维护每个点的vali−valfaili即可。

因为字符集很大,离散化以后也开不下,可以用map存转移。

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=200010;
map<int,int> trans[maxn];
int fail[maxn],val[maxn],n,tot=1;
void check()
{
for (int i=1;i<=tot;i++)
for (map<int,int>::iterator it=trans[i].begin();it!=trans[i].end();++it)
printf("%d-%d->%d\n",i,(*it).first,(*it).second);
}
int main()
{
LL ans=0;
int last=1,p,np,q,nq,x;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
p=last;
val[last=np=++tot]=val[p]+1;
while (p&&!trans[p].count(x))
{
trans[p][x]=np;
p=fail[p];
}
if (!p) fail[np]=1,ans+=val[np];
else
{
q=trans[p][x];
if (val[q]==val[p]+1) fail[np]=q,ans+=val[np]-val[q];
else
{
val[nq=++tot]=val[p]+1;
fail[nq]=fail[q];
fail[np]=fail[q]=nq;
trans[nq]=trans[q];
while (p&&trans[p][x]==q)
{
trans[p][x]=nq;
p=fail[p];
}
ans+=val[np]-val[nq];
}
}
//if (i==5) check();
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  SAM