生成魔咒 LibreOJ - 2033
阿新 • • 發佈:2020-07-31
sam上dp。可以將trans[s,c]看成是邊,整個sam就是一個dag圖。我們令dp[u]表示u結尾的,不同字串個數有多少即可。
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<set> #include<bitset> #include<map> #include<regex> #include<cstdio> #include <iomanip> #pragma GCC optimize(2) #define up(i,a,b) for(int i=a;i<b;i++) #define dw(i,a,b) for(int i=a;i>b;i--) #define upd(i,a,b) for(int i=a;i<=b;i++) #define dwd(i,a,b) for(int i=a;i>=b;i--) #define local typedef long long ll; typedef unsigned long long ull; const double esp = 1e-6; const double pi = acos(-1.0); const int INF = 0x3f3f3f3f; const int inf = 1e9; using namespace std; ll read() { char ch = getchar(); ll x = 0, f = 1; while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } typedef pair<int, int> pir; #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lrt root<<1 #define rrt root<<1|1 const int N = 1e5 + 10; struct sam { int len[N << 1]; ll dp[N << 1]; vector<map<int, int> >trans; vector<int>par; int last; int tot; int sz[N << 1]; void init(int l) { trans.resize(l + 1, map<int, int>()); par.resize(l + 1, 0); dp[1] = 1; last = 1; tot = 1; } ll ins(int c) { int pre = last; int now = last = ++tot; sz[now] = 1; len[now] = len[pre] + 1; for (; pre && !trans[pre][c]; pre = par[pre]) { //int t = trans[pre][c]; trans[pre][c] = now; dp[now] += dp[pre]; } if (pre == 0) { par[now] = 1; return dp[now]; } int ano = trans[pre][c]; if (len[ano] == len[pre] + 1) { par[now] = ano;} else { int nnow = ++tot; trans[nnow] = trans[ano]; len[nnow] = len[pre] + 1; par[nnow] = par[ano]; par[ano] = par[now] = nnow; for (; pre&&trans[pre][c] == ano; pre = par[pre]) { dp[nnow] += dp[pre]; trans[pre][c] = nnow; } dp[ano] -= dp[nnow]; } return dp[now]; } }S; int n; int x[N]; int main() { n = read(); S.init(2 * n); ll ans = 0; upd(i, 1, n) { x[i] = read(); ans += S.ins(x[i]); printf("%lld\n",ans); } return 0; }