1. 程式人生 > >hihocoder 1457(後綴自動機+拓撲排序)

hihocoder 1457(後綴自動機+拓撲排序)

十進制 重復 space cout add pac 不重復 min !=

題意

給定若幹組由數字構成的字符串,求所有不重復子串的和(把他們看成十進制),答案mod(1e9+7)

題解:

類似後綴數組的做法,把字符串之間用‘:‘連接,這裏用‘:‘是因為‘:‘的ascii碼恰好是9的下一個

然後建立後綴自動機。

之後把其實只要把其中的所有‘:‘邊刪去,就可以進行轉移了

如果x連向了y,邊權是c,那麽有轉移

dp[y] += dp[x]*10 + c*sz[x]

所以只要拓撲排序一下就好

(寫這題wa了好幾次,主要是在刪邊建立新圖的過程出了問題)

#include <iostream>
#include <cstring>
#include 
<cstdio> #include <queue> using namespace std; typedef long long LL; int n = 0, len, st; const int maxL = 2e6 + 100; const int MOD = 1e9 + 7; int maxlen[2*maxL], minlen[2*maxL], trans[2*maxL][12], slink[2*maxL], col[2*maxL]; LL in[2*maxL], dp[2*maxL], sz[2*maxL]; int new_state(int _maxlen, int
_minlen, int *_trans, int _slink){ maxlen[n] = _maxlen; minlen[n] = _minlen; for(int i = 0; i < 11; i++){ if(_trans == NULL) trans[n][i] = -1; else trans[n][i] = _trans[i]; } slink[n] = _slink; return n++; } int add_char(char ch, int
u){ int c = ch - 0; int z = new_state(maxlen[u]+1, -1, NULL, -1); int v = u; while(v != -1 && trans[v][c] == -1){ trans[v][c] = z; v = slink[v]; } if(v == -1){ minlen[z] = 1; slink[z] = 0; return z; } int x = trans[v][c]; if(maxlen[v] + 1 == maxlen[x]){ minlen[z] = maxlen[x] + 1; slink[z] = x; return z; } int y = new_state(maxlen[v] + 1, -1, trans[x], slink[x]); slink[y] = slink[x]; minlen[x] = maxlen[y] + 1; slink[x] = y; minlen[z] = maxlen[y] + 1; slink[z] = y; int w = v; while(w != -1 && trans[w][c] == x){ trans[w][c] = y; w = slink[w]; } minlen[y] = maxlen[slink[y]] + 1; return z; } char str[maxL]; queue<int> Q; int main() { freopen("a.txt", "r", stdin); int N; cin>>N; st = new_state(0, 0, NULL, -1); while(N--){ cin>>str; int len = strlen(str); for(int i = 0; i < len; i++) { st = add_char(str[i], st); } st = add_char(:, st); } Q.push(0); col[0] = 1; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int c = 0; c < 10; c++){ int y = trans[x][c]; if(y == -1) continue; if(!col[y]) Q.push(y); col[y] = 1; in[y]++; } } Q.push(0); sz[0] = 1; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int c = 0; c < 10; c++){ int y = trans[x][c]; if(y == -1) continue; in[y]--; if(in[y] == 0) Q.push(y); (sz[y] += sz[x]) %= MOD; (dp[y] += dp[x]*10 + c*sz[x]) %= MOD; } } LL ans = 0; /* for(int i = 0; i < n; i++){ for(int c = 0; c < 10; c++){ if(trans[i][c] == -1) continue; cout<<i<<" "<<trans[i][c]<<" "<<c<<endl; } }*/ //for(int i = 0; i < n; i++) cout<<dp[i]<<" "; cout<<endl; for(int i = 0; i < n; i++) (ans += dp[i]) %= MOD; cout<<ans<<endl; return 0; }

hihocoder 1457(後綴自動機+拓撲排序)