雙回文pam寫法

2021-07-17 03:33:39 字數 1497 閱讀 9893

lx神犇說我這種寫法就是核彈打蚊子。。。但是我不會馬拉車啊。而且這個演算法也是我上通技課的時候突然想到的。。。首先pam這個東西非常神而且特別好記憶(雖然一開始被坑了一下)基本上熟了之後敲板子都不怎麼要動腦子。而且功能異常強大。但是對於這道題我們構想雙回文首先他肯定要是四的倍數其次他要是回文串。對於這兩點pam做起來都很容易。然後怎麼判斷在回文串中平分之後還是回文串呢。顯然我們應該到失陪邊那裡找線索。然後顯然當l[x]=k; l[fail[fail[fail…..fail[x]],也就是某個類似於祖先的東西值等於k/2那麼這件事就搞定了。如何快速找到=k/2的祖先呢。首先根據失陪邊重新建造一棵樹這是很顯然的。然後我是寫了乙個樹上倍增解決的。還有一點值得一提。這題128mb竟然害我一開始mle…後來把pam陣列公用了才卡過記憶體。。。

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define maxn 500005

#define forup(i,a,b) for(inti=a;i<=b;i++)

#define fordown(i,a,b) for(inti=a;i>=b;i--)

#define pb push_back

#define a fa

vectorg[maxn];

int deep[maxn];

char s[maxn];

int n;

intfa[maxn][26];

struct pam

if(!a[p][c])

pam;

void dfs(int x)

for(int i=1; i<24; i++)

if(deep[x]<(1for(int i=0;iint v=g[x][i];

fa[v][0]=x;

deep[v]=deep[x]+1;

dfs(v);

bool work(int x)

{ int tmp=pam.l[x]>>1;

while(true)

{ int i; for(i=0;i<24;i++)

{ if(deep[x]<(iif(i==-1)

{if(pam.l[x]==tmp) return 1;

else  return 0;

x=fa[x][i];

int main()

{ cin>>n;

scanf("%s",s+1);

forup(i,1,n)

{pam.extend(s[i]-'a',i);

/* forup(i,0,pam.cnt)

{coutdfs(1);

intans=0;

forup(i,2,pam.cnt)  

{ //coutans=max(pam.l[i],ans);

//cout

回文自動機(PAM) 學習筆記

無。強行說和kmp有關也是可以的 1.乙個長度為 n 的字串最多有 n 個本質不同的回文子串。2.對於乙個字串 s,如果在其之後新插入乙個字元,那麼最多產生一種新的回文子串。證明 假設加入這個字元之後得到的最長回文字尾為 t,那麼對於長度小於 t 的任何回文字尾,它們必然在更前面的位置出現過。如圖所...

雙序列比對的基礎之PAM矩陣

pam矩陣的記分方法是基於蛋白序列中單點可接受 point accepted mutation,pam 的概念,通過對蛋白質進化模式的研究而建立的。pam矩陣是由dayhoff等人構建了與71個家族的序列關聯的假想系統發育樹,其中每對序列間的差異不超過它們殘基總數的15 用簡約法建樹,統計相似序列比...

P5496 模板 回文自動機(PAM)

題目背景 模板題,無背景 其實是我想不出背景 題目描述 給定乙個字串 s。保證每個字元為小寫字母。對於 s 的每個位置,請求出以該位置結尾的回文子串個數。這個字串被進行了加密,除了第乙個字元,其他字元都需要通過上乙個位置的答案來解密。具體地,若第 ii i 1 個位置的答案是 k,第 i 1 個字元...