首页 > 代码库 > bzoj 2434 阿狸的打字机 fail树的性质
bzoj 2434 阿狸的打字机 fail树的性质
如果a串是另b串的后缀,那么在trie图上沿着b的fail指针走一定可以走到a串。
而a串在b串里出现多少次就是它是多少个前缀的后缀。
所以把fail边反向建树维护个dfs序就行了。
并不是很难。。。但没想出来TAT
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200005 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 int n; 9 int ch[N][2], fa[N]; 10 int a[N]; 11 int mn[N],zhi[N],size[N]; 12 void push_up(int x) 13 { 14 size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; 15 mn[x] = min(zhi[x], min(mn[ch[x][0]], mn[ch[x][1]])); return; 16 } 17 int rev[N]; 18 void push_down(int x) 19 { 20 if (rev[x]) 21 { 22 rev[x] ^= 1; rev[ch[x][1]] ^= 1; rev[ch[x][0]] ^= 1; 23 swap(ch[x][0], ch[x][1]); 24 } 25 return; 26 } 27 void rotate(int p) 28 { 29 int q = fa[p], y = fa[q], x = (ch[q][1] == p); 30 ch[q][x] = ch[p][x ^ 1]; fa[ch[q][x]] = q; 31 ch[p][x ^ 1] = q; fa[q] = p; 32 fa[p] = y; 33 if (y) 34 { 35 if (ch[y][1] == q)ch[y][1] = p; 36 else ch[y][0] = p; 37 } 38 push_up(q); return; 39 } 40 int root; 41 void splay(int x,int yy) 42 { 43 for (int y; y = fa[x]; rotate(x)) 44 { 45 if (y == yy)break; 46 if (fa[y] != yy) 47 { 48 if ((ch[fa[y]][0] == y) ^ (ch[y][0] == x))rotate(x); 49 else rotate(y); 50 } 51 } 52 push_up(x); 53 if (!yy)root = x; 54 } 55 int cnt; 56 int find(int k, int x) 57 { 58 push_down(k); 59 if (mn[ch[k][0]] == x) 60 { 61 return find(ch[k][0], x); 62 } 63 if (zhi[k] == x)return size[ch[k][0]] + 1; 64 return find(ch[k][1], x) + size[ch[k][0]] + 1; 65 } 66 int fd(int k, int x) 67 { 68 push_down(k); 69 if (size[ch[k][0]] + 1 == x)return k; 70 if (size[ch[k][0]] + 1 >= x)return fd(ch[k][0],x); 71 return fd(ch[k][1], x - size[ch[k][0]] - 1); 72 } 73 struct node 74 { 75 int yuan,z; 76 friend bool operator < (node aa,node bb) 77 { 78 if(aa.z!=bb.z)return aa.z<bb.z; 79 return aa.yuan<bb.yuan; 80 } 81 }s[N]; 82 int yin[N]; 83 int main() 84 { 85 scanf("%d", &n); mn[0] = inf; 86 for (int i = 1; i <= n; i++) 87 { 88 s[i].yuan=i;scanf("%d",&s[i].z); 89 } 90 sort(s+1,s+n+1); 91 for(int i=1;i<=n;i++) 92 { 93 a[s[i].yuan]=i; 94 } 95 root = 1; a[n + 1] = inf; 96 ch[1][1] = 2; zhi[1] = a[1]; size[1] = n + 1; 97 for (int i = 2; i <= n + 1; i++) 98 { 99 size[i] = n - i + 2; 100 zhi[i] = a[i]; fa[i] = i - 1; ch[i - 1][1] = i; 101 } 102 for (int i = n + 1; i >= 1; i--)push_up(i); 103 splay(n, 0); 104 for (int i = 1; i <= n; i++) 105 { 106 int y = find(root, mn[root]); 107 if(i!=n)printf("%d ",y+(i-1)); 108 else printf("%d",y+(i-1)); 109 int t = fd(root, y+1); 110 splay(t, 0); 111 rev[ch[t][0]] ^= 1; 112 t = fd(root, 2); 113 splay(t, 0); 114 ch[t][0] = 0; 115 push_up(t); 116 } 117 puts(""); 118 return 0; 119 }
bzoj 2434 阿狸的打字机 fail树的性质
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。