2014-2015 ACM-ICPC, Asia Xian Regional Contest G題The Problem to Slow Down You(迴文樹)
阿新 • • 發佈:2019-01-31
題目大意:
給了兩個字串,問有多少個字串對,這個字串對要求,S1出現在第一個字串,S2出現在第二個字串且S1=S2,並且是迴文串。
思路:
看到題目就想到迴文樹了,然而一次這種題目都沒有寫過,導致我後來才發現我網上抄的模板是假的= =||。
建立兩個迴文樹,分別存下兩個字串,然後分別對它們的奇根和偶根跑一遍,把所有存在在兩個迴文樹裡的並且相等的串都統計一下就好了。
程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> const int maxn=2e5+5; char str[maxn]; typedef long long ll; using namespace std; ll ans=0; struct Palindromic_Tree { int next[maxn][26] ;//next指標,next指標和字典樹類似,指向的串為當前串兩端加上同一個字元構成 int fail[maxn] ;//fail指標,失配後跳轉到fail指標指向的節點 int cnt[maxn] ; //表示節點i表示的本質不同的串的個數(建樹時求出的不是完全的,最後count()函式跑一遍以後才是正確的) int num[maxn] ; //表示以節點i表示的最長迴文串的最右端點為迴文串結尾的迴文串個數 int len[maxn] ;//len[i]表示節點i表示的迴文串的長度(一個節點表示一個迴文串) int S[maxn] ;//存放新增的字元 int last ;//指向新新增一個字母后所形成的最長迴文串表示的節點。 int n ;//表示新增的字元個數。 int p ;//表示新增的節點個數。 int newnode ( int l ) //新建節點 { for ( int i = 0 ; i < 26 ; i++ ) next[p][i] = 0 ; cnt[p] = 0 ; num[p] = 0 ; len[p] = l ; return p ++ ; } void init () //初始化 { p = 0 ; newnode ( 0 ) ; newnode ( -1 ) ; last = 0 ; n = 0 ; S[n] = -1 ;//開頭放一個字符集中沒有的字元,減少特判 fail[0] = 1 ; } int get_fail ( int x ) //和KMP一樣,失配後找一個儘量最長的 { while ( S[n - len[x] - 1] != S[n] ) x = fail[x] ; return x ; } void add ( int c ) { c -= 'a' ; S[++ n] = c ; int cur = get_fail ( last ) ;//通過上一個迴文串找這個迴文串的匹配位置 if ( !next[cur][c] ) //如果這個迴文串沒有出現過,說明出現了一個新的本質不同的迴文串 { int now = newnode ( len[cur] + 2 ) ;//新建節點 fail[now] = next[get_fail ( fail[cur] )][c] ;//和AC自動機一樣建立fail指標,以便失配後跳轉 next[cur][c] = now ; num[now] = num[fail[now]] + 1 ; } last = next[cur][c] ; cnt[last] ++ ; } void count () { for ( int i = p - 1 ; i >= 0 ; -- i ) cnt[fail[i]] += cnt[i] ; //父親累加兒子的cnt,因為如果fail[v]=u,則u一定是v的子迴文串! } } tree1,tree2; void dfs(int x,int y) { for(int i=0; i<26; i++) { int son1=tree1.next[x][i],son2=tree2.next[y][i]; if(son1&&son2) { ans+=(ll)tree1.cnt[son1]*(ll)tree2.cnt[son2]; dfs(son1,son2); } } } int main() { int t,cas=1; scanf("%d",&t); while(t--) { ans=0; scanf("%s",str); tree1.init(),tree2.init(); int len=strlen(str); for(int i=0; i<len; i++) { tree1.add(str[i]); } scanf("%s",str); len=strlen(str); for(int i=0; i<len; i++) { tree2.add(str[i]); } tree1.count(); tree2.count(); dfs(0,0); dfs(1,1); printf("Case #%d: ",cas++); printf("%lld\n",ans); } return 0; } /* 3 abacab abccab faultydogeuniversity hasnopalindromeatall abbacabbaccab youmayexpectedstrongsamplesbutnow */