SPOJ Lexicographical Substring Search 后缀自动机

来源:互联网 发布:php 随机昵称生成器 编辑:程序博客网 时间:2024/05/19 06:48

给定一个字符串,取出所有的子串按照字典序排序并去重后,求第K大的子串。


以为自动机写错了。。后来发现是DP出的问题。 后缀自动机先告一段落,整理点东西出来吧!比赛时候出裸题,我得保证能做出来才行。


#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;const int CHAR = 26;const int MAXN = 250000 * 2  + 100;char str[MAXN];bool duanyan(bool flag, const string &x){if (!flag){cout << x << endl;throw 0;exit(0);}}struct SAM_Node{SAM_Node *fa, *next[CHAR];int len;int id, pos;long long dp;SAM_Node(){}SAM_Node(int _len){fa = 0;len = _len;dp=0;memset(next, 0, sizeof(next));}};SAM_Node SAM_node[MAXN *2], *SAM_root, *SAM_last;int SAM_size;SAM_Node * newSAM_Node(int len){SAM_node[SAM_size] = SAM_Node(len);SAM_node[SAM_size].id = SAM_size; SAM_node[SAM_size].dp = 0; return &SAM_node[SAM_size++];}SAM_Node *newSAM_Node(SAM_Node *p){SAM_node[SAM_size] = *p;SAM_node[SAM_size].id = SAM_size;SAM_node[SAM_size].dp = 0; return &SAM_node[SAM_size++];}void SAM_init(){SAM_size = 0;SAM_root = SAM_last = newSAM_Node(0);SAM_node[0].pos = 0;}void SAM_add(int x, int len){SAM_Node *p = SAM_last, *np = newSAM_Node(p -> len+1);np -> pos = len;SAM_last = np;for (;p && !p -> next[x]; p = p -> fa)p -> next[x] = np;if (!p){np -> fa = SAM_root;return;}SAM_Node *q = p -> next[x];if (q -> len == p-> len+1){np -> fa = q;return;}SAM_Node *nq = newSAM_Node(q);nq -> len = p -> len + 1;q -> fa = nq;np -> fa = nq;for (;p && p-> next[x] == q; p = p -> fa)p -> next[x] = nq;}int topcnt[MAXN];SAM_Node *topsam[MAXN*2];void SAM_build(char *s){SAM_init();int len = strlen(s);for (int i = 0 ;i < len; ++ i)SAM_add(s[i] - 'a' , i + 1);}int g[MAXN], f[MAXN];void pg(){for (int i = 0; i < SAM_size; ++ i){cout <<"@"<< SAM_node[i].id<< endl;for (int j = 0; j < 26; ++ j){if (SAM_node[i].next[j]){cout << SAM_node[i].next[j] -> id << endl;}}if (i)cout << "fa: " << SAM_node[i].fa -> id << endl;cout<<"===="<<endl;}}void find(SAM_Node* now, long long k){while (k){//--k;for (int i = 0; i < 26; ++ i){if (now -> next[i]){if (k <= (now -> next[i] -> dp)){putchar(i+'a');//TODOnow = now -> next[i];--k; //why here???break;}else{k -= now -> next[i] -> dp;}}}}putchar('\n');}int main(){int t;scanf("%s", str);SAM_build(str);int n = strlen(str);memset(topcnt, 0, sizeof(topcnt));for (int i = 0; i < SAM_size; ++ i)topcnt[SAM_node[i].len] ++ ;for (int i = 1; i <= n; ++ i)topcnt[i] += topcnt[i - 1];for (int i = 0; i < SAM_size ; ++ i)topsam[-- topcnt[SAM_node[i].len]] = &SAM_node[i];for (int i = 1; i < SAM_size; ++ i)SAM_node[i].dp = 1;for (int i = SAM_size -1; i>=0; -- i){SAM_Node *now = topsam[i];for (int i = 0; i < 26; ++ i){if (now->next[i]){now->dp += now->next[i]->dp;}}}scanf("%d", &t);pg();while (t--){long long k;scanf("%lld", &k);//if (k> SAM_root->dp)continue;find(SAM_root, k);//cout<<"=========================="<<endl;}return 0;}


阅读全文
0 0
原创粉丝点击