您的位置:首页 > 其它

hdu 4622 Reincarnation(后缀自动机,入门级)

2015-08-09 14:46 435 查看
题意:

求字符串任意字串的不同字串数。

思路:

用后缀自动机可以做到 O(n2)O(n^2)预处理,O(1)O(1)回答查询。

不过我的代码跑了 1000+ms

别人的代码可以跑到 100ms-200ms。。

VJ的记录

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <set>
#include <queue>
#include <cmath>
using namespace std;
#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
const int N = 2005;
typedef long long LL;

struct State {
State *link, *go[26];
int len;
void clear() {
link = 0; len = 0; memset(go, 0, sizeof(go));
}
int calc() {
if ( link == 0 ) return 0;
return len - link->len;
}
} *root, *last, *cur;

const int MaxLength = N;
State statePool[MaxLength*2];

void init() {
cur = statePool;
root = last = cur ++;
root->clear();
}

int tot = 0;

void sa_insert(int ch) {
//cout << "Insert " << (char)ch << endl;
ch -= 'a';
State *p = last;
State *np = cur ++;
np->clear();
np->len = p->len + 1;
while ( p && !p->go[ch] ) {
p->go[ch] = np; p = p->link;
}
if ( p == 0 ) {
np->link = root;
} else {
State *q = p->go[ch];
if ( p->len + 1 == q->len ) {
np->link = q;
} else {
State *nq = cur ++;
nq->clear();
memcpy(nq->go, q->go, sizeof(q->go));

tot -= q->calc();

nq->len = p->len + 1;
nq->link = q->link;
q->link = nq;
np->link = nq;

tot += q->calc() + nq->calc();

while( p && p->go[ch] == q ) {
p->go[ch] = nq; p = p->link;
}
}
}
tot += np->calc();
last = np;
}

int cnt

, n;
char buf
;

int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
int t;
scanf("%d", &t);
while ( t -- ) {
scanf("%s", buf);
//cout << buf << endl;
scanf("%d", &n);
int len = strlen(buf);
rep(i, 0, len-1) {
init();
tot = 0;
rep(j, i, len-1) {
sa_insert(buf[j]);
cnt[i][j] = tot;
}
}
rep(i, 1, n) {
int l, r;
scanf("%d%d", &l, &r);
-- l, -- r;
printf("%d\n", cnt[l][r]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: