Data update
This commit is contained in:
parent
4d5544505c
commit
4924dd0264
3073 changed files with 55820 additions and 4408 deletions
181
Task/Eertree/Zig/eertree.zig
Normal file
181
Task/Eertree/Zig/eertree.zig
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
const std = @import("std");
|
||||
|
||||
const evenRoot = 0;
|
||||
const oddRoot = 1;
|
||||
|
||||
const Node = struct {
|
||||
length: i32,
|
||||
edges: std.StringHashMap(usize),
|
||||
suffix: usize,
|
||||
|
||||
fn init(l: i32) Node {
|
||||
return .{
|
||||
.length = l,
|
||||
.edges = std.StringHashMap(usize).init(std.heap.page_allocator),
|
||||
.suffix = 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn initWithValues(l: i32, s: usize) Node {
|
||||
return .{
|
||||
.length = l,
|
||||
.edges = std.StringHashMap(usize).init(std.heap.page_allocator),
|
||||
.suffix = s,
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *Node) void {
|
||||
self.edges.deinit();
|
||||
}
|
||||
};
|
||||
|
||||
fn eertree(allocator: std.mem.Allocator, s: []const u8) !std.ArrayList(Node) {
|
||||
var tree = std.ArrayList(Node).init(allocator);
|
||||
|
||||
// Initialize the two roots
|
||||
const node0 = Node.initWithValues(0, oddRoot);
|
||||
const node1 = Node.initWithValues(-1, oddRoot);
|
||||
|
||||
try tree.append(node0);
|
||||
try tree.append(node1);
|
||||
|
||||
var suffix: usize = oddRoot;
|
||||
var n: usize = 0;
|
||||
var k: i32 = 0;
|
||||
|
||||
for (s, 0..) |c, i| {
|
||||
// Find the longest palindrome suffix
|
||||
n = suffix;
|
||||
while (true) {
|
||||
k = tree.items[n].length;
|
||||
const b: i64 = @as(i64, @intCast(i)) - k - 1;
|
||||
if (b >= 0 and s[@intCast(b)] == c) {
|
||||
break;
|
||||
}
|
||||
n = tree.items[n].suffix;
|
||||
}
|
||||
|
||||
// Convert char to string key for the hashmap
|
||||
var c_buf: [1]u8 = undefined;
|
||||
c_buf[0] = c;
|
||||
const c_key = c_buf[0..];
|
||||
|
||||
// Check if edge already exists
|
||||
if (tree.items[n].edges.get(c_key)) |found_suffix| {
|
||||
suffix = found_suffix;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create new node
|
||||
suffix = tree.items.len;
|
||||
const new_node = Node.init(k + 2);
|
||||
try tree.append(new_node);
|
||||
|
||||
try tree.items[n].edges.put(try allocator.dupe(u8, c_key), suffix);
|
||||
|
||||
if (tree.items[suffix].length == 1) {
|
||||
tree.items[suffix].suffix = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find suffix link
|
||||
while (true) {
|
||||
n = tree.items[n].suffix;
|
||||
const b: i64 = @as(i64, @intCast(i)) - tree.items[n].length - 1;
|
||||
if (b >= 0 and s[@intCast(b)] == c) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const suffix_edge = tree.items[n].edges.get(c_key) orelse unreachable;
|
||||
tree.items[suffix].suffix = suffix_edge;
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
fn subPalindromes(allocator: std.mem.Allocator, tree: std.ArrayList(Node)) !std.ArrayList([]const u8) {
|
||||
var results = std.ArrayList([]const u8).init(allocator);
|
||||
|
||||
const collectChildren = struct {
|
||||
fn collect(
|
||||
alloc: std.mem.Allocator,
|
||||
results_list: *std.ArrayList([]const u8),
|
||||
tree_list: *const std.ArrayList(Node),
|
||||
node_idx: usize,
|
||||
palindrome: []const u8
|
||||
) !void {
|
||||
var it = tree_list.items[node_idx].edges.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const c = entry.key_ptr.*[0];
|
||||
const next_node = entry.value_ptr.*;
|
||||
|
||||
// Create new palindrome by adding character to both sides
|
||||
var new_pal = try alloc.alloc(u8, palindrome.len + 2);
|
||||
new_pal[0] = c;
|
||||
@memcpy(new_pal[1 .. palindrome.len + 1], palindrome);
|
||||
new_pal[palindrome.len + 1] = c;
|
||||
|
||||
try results_list.append(new_pal);
|
||||
try collect(alloc, results_list, tree_list, next_node, new_pal);
|
||||
}
|
||||
}
|
||||
}.collect;
|
||||
|
||||
// Process even-length palindromes (from root 0)
|
||||
try collectChildren(allocator, &results, &tree, 0, "");
|
||||
|
||||
// Process odd-length palindromes (from root 1)
|
||||
var it = tree.items[1].edges.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const c = entry.key_ptr.*[0];
|
||||
const next_node = entry.value_ptr.*;
|
||||
|
||||
// Single character palindrome
|
||||
var c_pal = try allocator.alloc(u8, 1);
|
||||
c_pal[0] = c;
|
||||
try results.append(c_pal);
|
||||
|
||||
try collectChildren(allocator, &results, &tree, next_node, c_pal);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const input = "eertree";
|
||||
|
||||
var tree = try eertree(allocator, input);
|
||||
defer {
|
||||
for (tree.items) |*node| {
|
||||
node.deinit();
|
||||
}
|
||||
tree.deinit();
|
||||
}
|
||||
|
||||
var palindromes = try subPalindromes(allocator, tree);
|
||||
defer {
|
||||
for (palindromes.items) |pal| {
|
||||
allocator.free(pal);
|
||||
}
|
||||
palindromes.deinit();
|
||||
}
|
||||
|
||||
// Print results
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
try stdout.print("[", .{});
|
||||
|
||||
if (palindromes.items.len > 0) {
|
||||
try stdout.print("{s}", .{palindromes.items[0]});
|
||||
|
||||
for (palindromes.items[1..]) |pal| {
|
||||
try stdout.print(", {s}", .{pal});
|
||||
}
|
||||
}
|
||||
|
||||
try stdout.print("]\n", .{});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue