题解 P4341 【[BJWC2010]外星联络】
EternalAlexander · · 题解
写完看了下其他人代码,正解似乎是SA。
但是既然n^2的Trie树简单应用可以过那还写啥后缀数组是吧。
直接暴力枚举子串,将trie树上对应位置的cnt值+1,最后先序遍历一遍就完了。因为子串只有n^2个,字符集大小为2,因此时空复杂度均为n^2。
n<=3000 n^2是肯定可以过的。
估计是最简单,代码最短的做法了。
#include <cstdio>
int ch[9000000][2]={0};
int cnt[9000000]={0};
int tail=0;
char s[4000];
int dfs(int root) {
if (cnt[root]>1) printf("%d\n",cnt[root]);
if (ch[root][0]) dfs(ch[root][0]);
if (ch[root][1]) dfs(ch[root][1]);
return 0;
}
int main() {
int n;
scanf("%d %s", &n, &s);
for (int i=n;i>=1;--i) s[i]=s[i-1];
for (int i=1;i<=n;++i) {
int p=0;
for (int j=i;j<=n;++j) {
if (!ch[p][s[j]-'0']) ch[p][s[j]-'0']=++tail;
p=ch[p][s[j]-'0']; cnt[p]++;
}
}dfs(0);
return 0;
}