結果
| 問題 |
No.263 Common Palindromes Extra
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-03-14 00:08:44 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 261 ms / 2,000 ms |
| コード長 | 3,325 bytes |
| コンパイル時間 | 2,147 ms |
| コンパイル使用メモリ | 209,116 KB |
| 最終ジャッジ日時 | 2025-02-11 11:03:03 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 12 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
template<typename T = char>
struct MultiPalindromicTree{
private:
struct Node{
map<T, int> link;
int link_rev = -1;
int suffix_link = -1; // same suffix maximum pal
int len; // palindrome length
array<int, 2> cnt; // freq of this
pair<int, int> idx; // one of the start pos
Node() = default;
Node(int len): len(len), cnt{}, idx(-1, -1) {}
int succ(const T &c) const {
auto it = link.find(c);
if(it == link.end()) return -1;
return it->second;
}
};
// find longest P s.t. c + P + c is pal
int find_next_pal(int p, int k) const {
int pos = int(seq[p].size()) - 1;
while(true){
int i = pos - 1 - nodes[k].len;
if(i >= 0 && seq[p][i] == seq[p][pos]) return k;
k = nodes[k].suffix_link;
}
}
public:
vector<Node> nodes;
array<vector<T>, 2> seq = {};
array<int, 2> suffix_max = {};
MultiPalindromicTree(){
nodes.emplace_back(-1); // odd node
nodes.emplace_back(0); // even node
nodes[1].suffix_link = 0;
}
void add(int i, const T &c){
seq[i].push_back(c);
int k = find_next_pal(i, suffix_max[i]);
// c + P + c is already exists
if(int p = nodes[k].succ(c); p != -1){
++nodes[p].cnt[i];
suffix_max[i] = p;
return;
}
// unique
nodes[k].link[c] = suffix_max[i] = int(nodes.size());
int len = nodes[k].len + 2;
nodes.emplace_back(len);
nodes.back().cnt[i] = 1;
nodes.back().idx = {i, int(seq[i].size()) - len};
nodes.back().link_rev = k;
if(len == 1) nodes.back().suffix_link = 1;
else nodes.back().suffix_link =
nodes[find_next_pal(i, nodes[k].suffix_link)].link[c];
}
template<class Iiter>
void add(int i, Iiter first, Iiter last){
for(; first != last; ++first) add(i, *first);
}
template<class Container>
void add(int i, const Container &c){
add(i, begin(c), end(c));
}
// idx of suffix palindromes of node k
vector<int> suffix_palindromes(int k) const {
vector<int> ret;
for(; nodes[k].len > 0; k = nodes[k].suffix_link){
ret.push_back(k);
}
return ret;
}
// idx of substring palindromes of node k
vector<int> substr_palindroms(int k) const {
vector<int> ret, seen(nodes.size());
queue<int> qu;
qu.push(k); seen[k] = 1;
for(; !qu.empty(); qu.pop()){
int v = qu.front();
ret.push_back(v);
for(int u : {nodes[v].suffix_link, nodes[v].link_rev}){
if(!seen[u]) qu.push(u), seen[u] = 1;
}
}
return ret;
}
// not count ""
int count() const { return int(nodes.size()) - 2; }
vector<array<int, 2>> palindromes_frequency() const {
int m = int(nodes.size());
vector<array<int, 2>> freq(m);
for(int i = m - 1; i >= 1; --i){
for(int j = 0; j < 2; ++j){
freq[i][j] += nodes[i].cnt[j];
freq[nodes[i].suffix_link][j] += freq[i][j];
}
}
return freq;
}
const Node &operator[](int k) const { return nodes[k]; }
};
int main() {
MultiPalindromicTree mpt;
string s, t; cin >> s >> t;
mpt.add(0, s);
mpt.add(1, t);
auto freq = mpt.palindromes_frequency();
int64_t ans = 0;
for(int i = 0; i < mpt.count(); ++i){
ans += freq[i + 2][0] * 1ll * freq[i + 2][1];
}
cout << ans << "\n";
}