結果
問題 | No.263 Common Palindromes Extra |
ユーザー |
|
提出日時 | 2016-06-10 12:22:11 |
言語 | Java (openjdk 23) |
結果 |
AC
|
実行時間 | 377 ms / 2,000 ms |
コード長 | 6,478 bytes |
コンパイル時間 | 3,938 ms |
コンパイル使用メモリ | 90,432 KB |
実行使用メモリ | 82,004 KB |
最終ジャッジ日時 | 2024-11-29 23:13:28 |
合計ジャッジ時間 | 7,532 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 12 |
ソースコード
package q3xx; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.InputMismatchException; public class Q399 { InputStream is; PrintWriter out; String INPUT = ""; void solve() { char[] s = ns().toCharArray(); char[] t = ns().toCharArray(); int n = s.length, m = t.length; char[] u = new char[n+2+m]; for(int i = 0;i < n;i++)u[i] = s[i]; u[n] = '$'; u[n+1] = '!'; for(int i = 0;i < m;i++)u[n+2+i] = t[i]; gn = n; PalindromicTree2 pt = new PalindromicTree2(u); long ret = 0; for(int i = 2;i < pt.gen;i++){ ret += (long)pt.freqs0[i] * pt.freqs1[i]; } out.println(ret); } static int gn; public static class PalindromicTree2 { int[] firsts, lens, freqs, freqs0, freqs1; int[] firstChilds, nexts, links; char[] cs; int gen; public PalindromicTree2(char[] s) { build(s); } public int newNode(int first, int len, char c) { firsts[gen] = first; lens[gen] = len; cs[gen] = c; freqs[gen] = 0; freqs0[gen] = 0; freqs1[gen] = 0; firstChilds[gen] = -1; links[gen] = -1; nexts[gen] = -1; return gen++; } public int next(char x, int id) { for(int ch = firstChilds[id];ch != -1;ch = nexts[ch]){ if(cs[ch] == x)return ch; } return -1; } public void add(int x, int id) { int ch = firstChilds[id]; firstChilds[id] = x; nexts[x] = ch; } public String toString(int id) { return "Node [id=" + id + ", first=" + firsts[id] + ", len=" + lens[id] + ", freq=" + freqs[id] + ", c=" + cs[id] + ", firstChild=" + firstChilds[id] + ", sibling=" + nexts[id] + ", link=" + links[id] + "]"; } public void build(char[] s) { assert gen == 0; int n = s.length; firsts = new int[n+2]; lens = new int[n+2]; freqs = new int[n+2]; freqs0 = new int[n+2]; freqs1 = new int[n+2]; firstChilds = new int[n+2]; nexts = new int[n+2]; links = new int[n+2]; cs = new char[n+2]; int hell = newNode(-1, -1, (char)0); int zero = newNode(-1, 0, (char)0); assert hell == 0; assert zero == 1; links[zero] = hell; links[hell] = hell; add(zero, hell); int cur = zero; // current suffix palindrome for(int i = 0;i < n;i++){ char x = s[i]; while(i-lens[cur]-1 < 0 || s[i-lens[cur]-1] != x)cur = links[cur]; // find xAx int xax = next(x, cur); // already exists if(xax == -1){ // new subpalindrome xax = newNode(i-lens[cur]-1, lens[cur]+2, x); add(xax, cur); // make suffix link if(lens[xax] == 1){ links[xax] = zero; }else{ int b = links[cur]; while(true){ while(i-lens[b]-1 < 0 || s[i-lens[b]-1] != x)b = links[b]; // find xBx int xbx = next(x, b); if(xbx != -1){ links[xax] = xbx; break; } } } } // [i-cur.len-1, i] freqs[xax]++; // increment regardless new or not if(i < gn){ freqs0[xax]++; }else if(i-lens[cur]-1 >= gn+2){ freqs1[xax]++; } cur = xax; } for(int i = gen-1;i >= 2;i--){ freqs[links[i]] += freqs[i]; freqs0[links[i]] += freqs0[i]; freqs1[links[i]] += freqs1[i]; } } public String toDot(boolean next, boolean suffixLink) { StringBuilder sb = new StringBuilder("digraph{\n"); sb.append("graph[rankdir=LR];\n"); sb.append("node[shape=circle];\n"); for(int i = 0;i < gen;i++){ if(suffixLink && links[i] != -1){ sb.append("\"" + i + "\"") .append("->") .append("\"" + links[i] + "\"") .append("[style=dashed];\n"); } if(next){ for(int ch = firstChilds[i]; ch != -1;ch = nexts[ch]){ sb.append("\"" + i + "\"") .append("->") .append("\"" + ch + "\"") .append("[label=\"") .append(cs[ch] == 0 ? ' ' : cs[ch]) .append("\"];\n"); } } } sb.append("}\n"); return sb.toString(); } } void run() throws Exception { is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes()); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms"); } public static void main(String[] args) throws Exception { new Q399().run(); } private byte[] inbuf = new byte[1024]; private int lenbuf = 0, ptrbuf = 0; private int readByte() { if(lenbuf == -1)throw new InputMismatchException(); if(ptrbuf >= lenbuf){ ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if(lenbuf <= 0)return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char)skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while(p < n && !(isSpaceChar(b))){ buf[p++] = (char)b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for(int i = 0;i < n;i++)map[i] = ns(m); return map; } private int[] na(int n) { int[] a = new int[n]; for(int i = 0;i < n;i++)a[i] = ni(); return a; } private int ni() { int num = 0, b; boolean minus = false; while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')); if(b == '-'){ minus = true; b = readByte(); } while(true){ if(b >= '0' && b <= '9'){ num = num * 10 + (b - '0'); }else{ return minus ? -num : num; } b = readByte(); } } private long nl() { long num = 0; int b; boolean minus = false; while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')); if(b == '-'){ minus = true; b = readByte(); } while(true){ if(b >= '0' && b <= '9'){ num = num * 10 + (b - '0'); }else{ return minus ? -num : num; } b = readByte(); } } private static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); } }