[TJOI2013]单词
可以用后缀数组来做。
我说以下ac自动机的做法:
加入每个单词,对路径上的所有点累计访问次数。
构建fail指针。
把每个节点的访问次数累加到它的fail上。具体有代码。。(我写的很挫 - -)
/**
* Problem:Word
* Author:Shun Yao
* Time:2013.5.21
* Result:Accepted
* Memo:AC-automation
*/
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
long n, l, r;
char s[201][1000000];
class node {
public:
long v;
node *next[27], *fail;
node() {
v = 0;
}
~node() {}
} *root, *p, *q[1000000];
int main() {
static long i;
static char *ss;
freopen("word.in", "r", stdin);
freopen("word.out", "w", stdout);
scanf("%ld", &n);
root = new node();
for (i = 1; i <= n; ++i) {
scanf(" %s", s[i]);
p = root;
ss = s[i];
while (*ss) {
if (!p->next[*ss - 'a'])
p->next[*ss - 'a'] = new node();
p = p->next[*ss - 'a'];
++p->v;
++ss;
}
}
l = 0;
r = 0;
for (i = 0; i < 26; ++i)
if (root->next[i]) {
q[r++] = root->next[i];
root->next[i]->fail = root;
}
while (l < r) {
for (i = 0; i < 26; ++i)
if (q[l]->next[i]) {
q[r++] = q[l]->next[i];
p = q[l]->fail;
while (p != root && !p->next[i])
p = p->fail;
if (p->next[i])
q[l]->next[i]->fail = p->next[i];
else
q[l]->next[i]->fail = root;
}
++l;
}
for (i = r - 1; i >= 0; --i)
q[i]->fail->v += q[i]->v;
for (i = 1; i <= n; ++i) {
p = root;
ss = s[i];
while (*ss) {
if (!p->next[*ss - 'a'])
p->next[*ss - 'a'] = new node();
p = p->next[*ss - 'a'];
++ss;
}
printf("%ld\n", p->v);
}
fclose(stdin);
fclose(stdout);
return 0;
}
作者:HSUPPR
出处:http://www.cnblogs.com/hsuppr/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
原文链接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号