标签:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN = 2e6+7; const int oo = 1e9+7; struct Trie {///字典树的节点 int next[26]; int leaf;///以这个节点为终点的叶子节点个数 int count;///后面回文串的数量 void Free() { leaf = count = 0; memset(next, false, sizeof(next)); } }trie[MAXN]; int top;///配合字典树使用,top表示没有使用的内存 int start[MAXN], p[MAXN<<1]; char MumStr[MAXN], Estr[MAXN<<1]; bool suffix[MAXN];///后缀是否是回文串 bool prefix[MAXN];///前缀是否是回文串 void BuildTrie(int n) { int p = 0; for(int i=start[n+1]-1; i>=start[n]; i--) {///把字符串倒插进去 int k = MumStr[i] - ‘a‘; trie[p].count += prefix[i]; if(trie[p].next[k] == 0) { trie[p].next[k] = ++top; trie[top].Free(); } p = trie[p].next[k]; } trie[p].leaf += 1; } void Manacher(int n) { int i, id=0, len=1; Estr[0] = ‘$‘; for(i=start[n]; i<start[n+1]; i++) { Estr[len++] = ‘#‘; Estr[len++] = MumStr[i]; suffix[i] = false; prefix[i] = false; } Estr[len] = ‘#‘; Estr[len+1] = 0; for(i=2; i<len; i++) { p[i] = 1; if(p[id]+id > i) p[i] = min(p[id*2-i], p[id]+id-i); while(Estr[ i+p[i] ] == Estr[ i-p[i] ]) p[i]++; if(p[id]+id < p[i]+i) id = i; if(p[i] == i) prefix[ start[n]+p[i]-2 ] = true; if(p[i]+i-1 == len) suffix[ start[n+1]-p[i]+1 ] = true; } } int Query(int n) { int i, p=0, sum = 0; for(i=start[n]; i<start[n+1]; i++) { int k = MumStr[i] - ‘a‘; if(trie[p].next[k] == 0) break; p = trie[p].next[k]; if(suffix[i+1] || i==start[n+1]-1) sum += trie[p].leaf; } if(i == start[n+1]) sum += trie[p].count; return sum; } int main() { int N; while(scanf("%d", &N) != EOF) { int i, len; top = 0; trie[0].Free(); for(i=1; i<=N; i++) { scanf("%d%s", &len, MumStr+start[i]); start[i+1] = start[i] + len; Manacher(i); BuildTrie(i); } long long ans = 0; for(i=1; i<=N; i++) ans += Query(i); printf("%lld\n", ans); } return 0; } /** 2 3 abc 4 acba */
Finding Palindromes - 猥琐的字符串(Manacher+trie)
标签:
原文地址:http://www.cnblogs.com/liuxin13/p/4748749.html