結果
問題 | No.1845 Long Substrings |
ユーザー |
![]() |
提出日時 | 2025-03-29 04:33:08 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 245 ms / 2,000 ms |
コード長 | 1,892 bytes |
コンパイル時間 | 3,752 ms |
コンパイル使用メモリ | 285,940 KB |
実行使用メモリ | 16,248 KB |
最終ジャッジ日時 | 2025-03-29 04:33:18 |
合計ジャッジ時間 | 9,192 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 34 |
ソースコード
#include <bits/stdc++.h>#include <atcoder/modint>using namespace std;using namespace atcoder;using ll = long long;using mint = modint1000000007;int main(){cin.tie(nullptr);ios_base::sync_with_stdio(false);/*部分列DPdp(i) = i文字目まででの部分文字列の種類数c=a,...,zのi以降の最小のインデックスp_cにdp(p_c) += dp(i)dp(i) = i文字目の塊まででの部分文字列の種類数異なる文字(S_i != S_j) -> jのどこで止めるか?dp(j) += dp(i) * A_j同じ文字列(S_i == S_j) -> 重複を避けるために、A_iの末尾からの遷移しか許可しない。iiooiiA_1までi, ii (2)A_3までi+i, i+ii, ii+i, ii+ii (3)dp(i, j) = i文字目の塊までで、i文字目の塊を全て使った(j=1)か使ってない(j=0)ときの部分文字列の数*/int N;cin >> N;vector<int> A(N+1);for (int i=1; i<=N; i++) cin >> A[i];string S;cin >> S;S = '$' + S;char c;vector<vector<int>> v(26);for (int i=1; i<=N; i++){c = S[i];v[c-'a'].push_back(i);}mint ans=0;vector dp(N+1, vector<mint>(2));dp[0][0] = 1;for (int i=0; i<=N; i++){c = S[i];for (int j=0; j<26; j++){auto it = lower_bound(v[j].begin(), v[j].end(), i+1);if (it != v[j].end()){if (c-'a' == j){dp[*it][1] += dp[i][1];dp[*it][0] += dp[i][1] * (A[*it]-1);}else{dp[*it][1] += dp[i][1] + dp[i][0];dp[*it][0] += (dp[i][1] + dp[i][0]) * (A[*it]-1);}}}}for (int i=1; i<=N; i++) ans += dp[i][0] + dp[i][1];cout << ans.val() << endl;return 0;}