結果
| 問題 | No.263 Common Palindromes Extra |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-02-18 02:27:23 |
| 言語 | Go (1.25.5) |
| 結果 |
MLE
|
| 実行時間 | - |
| コード長 | 2,793 bytes |
| 記録 | |
| コンパイル時間 | 13,908 ms |
| コンパイル使用メモリ | 231,704 KB |
| 実行使用メモリ | 248,472 KB |
| 最終ジャッジ日時 | 2024-09-29 00:01:04 |
| 合計ジャッジ時間 | 13,812 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 11 MLE * 1 |
ソースコード
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
yuki263()
}
// No.263 Common Palindromes Extra
// 求两个字符串的公共回文子串的个数 n<=5e5
// https://yukicoder.me/problems/no/263
func yuki263() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var s, t string
fmt.Fscan(in, &s, &t)
T := NewPam()
T.AddString(s + "><" + t)
dps := make([]int, T.Size())
dpt := make([]int, T.Size())
lenS := int32(len(s))
for i := 0; i < T.Size(); i++ {
for _, j := range T.Nodes[i].Indexes { // 回文出现位置
if j < lenS {
dps[i]++
} else if j >= lenS+2 {
dpt[i]++
}
}
}
res := 0
for i := T.Size() - 1; i >= 2; i-- { // 按照拓扑序遍历本质不同回文
res += dps[i] * dpt[i]
dps[T.Nodes[i].Link] += dps[i]
dpt[T.Nodes[i].Link] += dpt[i]
}
fmt.Fprintln(out, res)
}
type Node struct {
Next map[int32]int32 // 子节点.
Link int32 // suffix link,指向当前回文串的最长真回文后缀的位置
Length int32 // 结点代表的回文串的长度
Indexes []int32 // 哪些位置的最长回文后缀
}
type Pam struct {
Ords []int32
Nodes []*Node
lastPos int32 // 当前字符串(原串前缀)的最长回文后缀
}
func NewPam() *Pam {
res := &Pam{}
res.Nodes = append(res.Nodes, res.newNode(0, -1)) // 奇根,长为 -1
res.Nodes = append(res.Nodes, res.newNode(0, 0)) // 偶根,长为 0
return res
}
func (pt *Pam) Add(x int32) int {
pos := int32(len(pt.Ords))
pt.Ords = append(pt.Ords, x)
cur := pt.findPrevPalindrome(pt.lastPos)
_, hasKey := pt.Nodes[cur].Next[x]
if !hasKey {
pt.Nodes[cur].Next[x] = int32(len(pt.Nodes))
}
pt.lastPos = pt.Nodes[cur].Next[x]
if !hasKey {
pt.Nodes = append(pt.Nodes, pt.newNode(-1, pt.Nodes[cur].Length+2))
if pt.Nodes[len(pt.Nodes)-1].Length == 1 {
pt.Nodes[len(pt.Nodes)-1].Link = 1
} else {
pt.Nodes[len(pt.Nodes)-1].Link = pt.Nodes[pt.findPrevPalindrome(pt.Nodes[cur].Link)].Next[x]
}
}
pt.Nodes[pt.lastPos].Indexes = append(pt.Nodes[pt.lastPos].Indexes, pos)
return int(pt.lastPos)
}
func (pt *Pam) AddString(s string) {
if len(s) == 0 {
return
}
for _, v := range s {
pt.Add(v)
}
}
func (pt *Pam) Size() int {
return len(pt.Nodes)
}
func (pt *Pam) GetNode(pos int) *Node {
return pt.Nodes[pos]
}
func (pt *Pam) newNode(link, length int32) *Node {
return &Node{
Next: make(map[int32]int32),
Link: link,
Length: length,
}
}
func (pt *Pam) findPrevPalindrome(cur int32) int32 {
pos := int32(len(pt.Ords) - 1)
for {
rev := pos - 1 - pt.Nodes[cur].Length
// !插入当前字符的条件str[i]==str[i-len-1]
if rev >= 0 && pt.Ords[rev] == pt.Ords[len(pt.Ords)-1] {
break
}
cur = pt.Nodes[cur].Link
}
return cur
}