回文树(回文自动机) - URAL 1960 Palindromes and Super Abilities
生活随笔
收集整理的這篇文章主要介紹了
回文树(回文自动机) - URAL 1960 Palindromes and Super Abilities
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
??Palindromes and Super Abilities
Problem's Link: ?http://acm.timus.ru/problem.aspx?space=1&num=1960
?
Mean:?
給你一個長度為n的字符串S,輸出S的各個前綴中回文串的數(shù)量。
analyse:
回文樹(回文自動機)的模板題。
由于回文自動機中的p是一個計數(shù)器,也相當于一個指針,記錄的是當前插入字符C后回文樹中有多少個節(jié)點。
那么我們只需要一路插,一路輸出p-2就行。
p-2是因為一開始回文樹中就有兩個節(jié)點。這是兩個根節(jié)點,分別是長度為偶數(shù)和奇數(shù)的回文串的根節(jié)點。
?
Time complexity: O(N)
?
Source code:?
/** this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-08-17-14.58
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define ?LL long long
#define ?ULL unsigned long long
using namespace std;
const int MAXN = 100005 ;
const int N = 26 ;
char s[MAXN];
namespace Palindromic_Tree
{
? ? ?int next[MAXN][N] ;//next指針,next指針和字典樹類似,指向的串為當前串兩端加上同一個字符構成
? ? ?int fail[MAXN] ;//fail指針,失配后跳轉到fail指針指向的節(jié)點
? ? ?int cnt[MAXN] ;
? ? ?int num[MAXN] ;
? ? ?int len[MAXN] ;//len[i]表示節(jié)點i表示的回文串的長度
? ? ?int S[MAXN] ;//存放添加的字符
? ? ?int last ;//指向上一個字符所在的節(jié)點,方便下一次add
? ? ?int n ;//字符數(shù)組指針
? ? ?int p ;//節(jié)點指針
? ? ?int newnode(int l) ? ? //新建節(jié)點
? ? ?{
? ? ? ? ? ?for(int i = 0 ; i < N ; ++ 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]) ? ? //如果這個回文串沒有出現(xiàn)過,說明出現(xiàn)了一個新的本質不同的回文串
? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?int now = newnode(len[cur] + 2) ; ? //新建節(jié)點
? ? ? ? ? ? ? ? ?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的子回文串!
? ? ?}
} ;
using namespace Palindromic_Tree;
int main()
{
? ? ?ios_base::sync_with_stdio(false);
? ? ?cin.tie(0);
? ? ?while(~scanf("%s",s))
? ? ?{
? ? ? ? ? ?init();
? ? ? ? ? ?for(int i=0;s[i];++i)
? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?add(s[i]);
? ? ? ? ? ? ? ? ?printf(i==0?"%d":" %d",p-2);
? ? ? ? ? ?}
? ? ? ? ? ?puts("");
// ? ? ? ? ? ?Count();
? ? ?}
? ? ?return 0;
}
/*
*/
代碼2:
/** this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-08-17-16.51
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define ?LL long long
#define ?ULL unsigned long long
using namespace std;
const int MAXN = 100010;
struct node
{
? ? ?int next[26];
? ? ?int len;
? ? ?int sufflink;
? ? ?int num;
};
int len;
char s[MAXN];
node tree[MAXN];
int num; // node 1 - root with len -1, node 2 - root with len 0
int suff; // max suffix palindrome
long long ans;
bool addLetter(int pos)
{
? ? ?int cur = suff, curlen = 0;
? ? ?int let = s[pos] - 'a';
? ? ?while(true)
? ? ?{
? ? ? ? ? ?curlen = tree[cur].len;
? ? ? ? ? ?if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos]) break;
? ? ? ? ? ?cur = tree[cur].sufflink;
? ? ?}
? ? ?if(tree[cur].next[let])
? ? ?{
? ? ? ? ? ?suff = tree[cur].next[let];
? ? ? ? ? ?return false;
? ? ?} suff = ++num;
? ? ?tree[num].len = tree[cur].len + 2;
? ? ?tree[cur].next[let] = num;
? ? ?if(tree[num].len == 1)
? ? ?{
? ? ? ? ? ?tree[num].sufflink = 2;
? ? ? ? ? ?tree[num].num = 1;
? ? ? ? ? ?return true;
? ? ?}
? ? ?while(true)
? ? ?{
? ? ? ? ? ?cur = tree[cur].sufflink;
? ? ? ? ? ?curlen = tree[cur].len;
? ? ? ? ? ?if(pos - 1 - curlen >= 0 && s[pos - 1 - curlen] == s[pos])
? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?tree[num].sufflink = tree[cur].next[let];
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?}
? ? ?}
? ? ?tree[num].num = 1 + tree[tree[num].sufflink].num;
? ? ?return true;
}
void initTree()
{
? ? ?num = 2; suff = 2;
? ? ?tree[1].len = -1; tree[1].sufflink = 1;
? ? ?tree[2].len = 0; tree[2].sufflink = 1;
}
int main()
{
? ? ?scanf("%s",s);
? ? ?len = strlen(s);
? ? ?initTree();
? ? ?for(int i = 0; i < len; i++)
? ? ?{
? ? ? ? ? ?addLetter(i);
? ? ? ? ? ?printf(i==0?"%d":" %d",num-2);
// ? ? ? ? ? ?ans += tree[suff].num;
? ? ?}
? ? ?putchar(10);
// ? ? ? cout << ans << endl;
? ? ?return 0;
}
?
轉載于:https://www.cnblogs.com/crazyacking/p/4736871.html
總結
以上是生活随笔為你收集整理的回文树(回文自动机) - URAL 1960 Palindromes and Super Abilities的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电子书下载网站整理
- 下一篇: Oracle递归查询