5052. 旅游路线
2017-04-14 12:39
274 查看
题目大意
给定一个n个点的tire,求有多少个不同的子串。Data Constraint
n≤105
题解
如果将tire上所有的串取出来,做一遍SA,显然就可以很方便的计算出答案了。所以考虑如何对tire做SA。
还是用倍增的方法,只是原来对一个串的倍增变成了树上的倍增。
求Height也是用倍增的方法求。
时间复杂度:O(nlogn)
我程序里偷了一下懒,没用基数排序多了一个log
SRC
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<map> #include<vector> using namespace std ; #define N 100000 + 10 typedef long long ll ; const int MAXN = 17 ; int f[N][MAXN] , Rank[N][MAXN] , SA ; int Node , Next , Head , tot ; int Deg , Deep ; int n , lasd ; ll ans ; void link( int u , int v ) { Node[++tot] = v ; Next[tot] = Head[u] ; Head[u] = tot ; } void DFS( int x ) { SA[x] = x ; for (int p = Head[x] ; p ; p = Next[p] ) { f[Node[p]][0] = x ; Deep[Node[p]] = Deep[x] + 1 ; Rank[Node[p]][0] = Deg[Node[p]] ; DFS( Node[p] ) ; } } bool cmp( int a , int b ) { return Rank[a][lasd] < Rank[b][lasd] || ( Rank[a][lasd] == Rank[b][lasd] && Rank[f[a][lasd]][lasd] < Rank[f[b][lasd]][lasd] ) ; } bool Equal( int x , int y ) { return Rank[x][lasd] == Rank[y][lasd] && Rank[f[x][lasd]][lasd] == Rank[f[y][lasd]][lasd] ; } int main() { freopen( "route.in" , "r" , stdin ) ; freopen( "route.out" , "w" , stdout ) ; scanf( "%d" , &n ) ; for (int i = 1 ; i < n ; i ++ ) { int u , v ; scanf( "%d%d" , &u , &v ) ; link( v , u ) ; Deg[u] ++ , Deg[v] ++ ; } Rank[1][0] = Deg[1] ; Deep[1] = 1 ; DFS( 1 ) ; for (int j = 1 ; j < MAXN ; j ++ ) { for (int i = 1 ; i <= n ; i ++ ) { f[i][j] = f[f[i][j-1]][j-1] ; } } for (int d = 1 ; d < MAXN ; d ++ ) { lasd = d - 1 ; sort( SA + 1 , SA + n + 1 , cmp ) ; int p = 1 ; Rank[SA[1]][d] = 1 ; for (int i = 2 ; i <= n ; i ++ ) { if ( !Equal( SA[i-1] , SA[i] ) ) p ++ ; Rank[SA[i]][d] = p ; } } for (int i = 1 ; i <= n ; i ++ ) { ans += Deep[SA[i]] ; int Height = 0 ; int x = SA[i-1] , y = SA[i] ; for (int j = MAXN - 1 ; j >= 0 ; j -- ) { if ( Deep[x] < (1 << j) || Deep[y] < (1 << j) ) continue ; if ( Rank[x][j] == Rank[y][j] ) { x = f[x][j] , y = f[y][j] ; Height += (1 << j) ; } } ans -= Height ; } printf( "%lld\n" , ans ) ; return 0 ; }
以上.
相关文章推荐
- JZOJ 5052. 【GDOI2017模拟二试4.12】旅游路线
- 最佳旅游路线
- [DP 倍增Floyd] LOJ#539.「LibreOJ NOIP Round #1」旅游路线
- [JZOJ5052]旅行路线
- Cpp环境【NOI1994】【Vijos3266】最佳旅游路线
- 【GDOI2017模拟二试4.12】旅游路线(后缀自动机,trie)
- [LOJ539] 旅游路线
- 游武大 登临珞珈——探武大旅游最佳路线
- NOI1994 最佳旅游路线 解题报告
- hhu 5177 旅游路线 floyd 解题报告
- 最佳旅游路线
- CODEVS 3300 旅游路线
- LOJ#539. 「LibreOJ NOIP Round #1」旅游路线
- 【最大子区间和】旅游路线(travel.pas/c/cpp)
- 旅游路线 解题报告
- 【jzoj5052】【旅游路线】【后缀数组】
- 「LibreOJ NOIP Round #1」旅游路线
- 最佳旅游路线
- 【最大子区间和】旅游路线(travel.pas/c/cpp)
- 【LibreOJ】#539. 「LibreOJ NOIP Round #1」旅游路线