您的位置:首页 > 其它

SPOJ NSUBSTR

2015-06-20 16:44 295 查看
题目大意:

给定一个字符串,求每个对应的长度能产生的相同子串的最大个数

这里构建好后缀自动机之后,再将整个字符串从头到尾扫一遍,然后将每个对应的点上的sc值+1

表示从头走到尾的前提下,所能产生的子串能够得到的最大数量为1

然后再去考虑其他子串

每个后缀自动机上的节点上的长度表示的是当前点所能接收的最大长度的后缀

我们只考虑这个最大长度即可,因为其他没考虑的长度,最后都不断通过dp[i] = max(dp[i] , dp[i+1]) 得到即可

拓扑排序后,从尾节点开始不断往前,相当于由子节点不断更新父节点所能得到的值

也就是b[i]->f->sc += b[i]->sc;

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
#define N 500010
#define M 26

struct SamNode{
SamNode *son[26] , *f;
int l , sc;
}*root , *last , sam
, *b
;

int cnt , dp
, num
;
char s
;

void init(){
root = last = &sam[cnt=0];
}

void add(int x)
{
SamNode *p = &sam[++cnt] , *jp=last;
p->l = jp->l+1;
last = p;
for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x]=p;
if(!jp) p->f = root;
else{
if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x];
else{
SamNode *r = &sam[++cnt] , *q = jp->son[x];
*r = *q;
r->l = jp->l+1;
q->f = p->f = r;
for( ; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
}
}
}

void solve()
{
init();
int len = strlen(s);
for(int i=0 ; i<len ; i++) add(s[i]-'a');
//后面三个for循环相当于进行拓扑排序
for(int i=0 ; i<=cnt ; i++) num[sam[i].l]++;
for(int i=1 ; i<=len ; i++) num[i]+=num[i-1];
for(int i=0 ; i<=cnt ; i++) b[--num[sam[i].l]] = &sam[i];

SamNode *cur = root;
for(int i=0 ; i<len ; i++){
cur = cur->son[s[i]-'a'];
cur->sc++;
}
for(int i=cnt ; i>0 ; i--){
int l = b[i]->l;
dp[l] = max(dp[l] , b[i]->sc);
b[i]->f->sc += b[i]->sc;
}
for(int i=len-1 ; i>=1 ; i--) dp[i]=max(dp[i] , dp[i+1]);
for(int i=1 ; i<=len ; i++) printf("%d\n" , dp[i]);
}

int main()
{
// freopen("a.in" , "r" , stdin);
scanf("%s" , s);
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: