字尾陣列水水水水水水題

2021-07-09 11:22:09 字數 4394 閱讀 9332

首先:

jxrjxrjxr orz,沒有您我們都會死~

然後就是我從jxr神犇那裡借鑑(照抄)過來的字尾陣列模板。

#include#include#include#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

using namespace std;

const int n=100000+1000;

char s[n];

int a[n],b[n],c[n],sa[n],rk[n],h[n],n,*x,*y;

void radix(int m)

void getsa(int m)

}void geth()

真是十分的  短  啊~~~~~~

話說我現在才會字尾陣列真的好嗎,簡直違反基本法啊。

不過還是稀里糊塗地看懂(背下來)了。

於是就可以開心地去水題了。

沒錯其實我就是把09年那篇**裡面的題給水了下。

然後來寫下一句話題解。

poj1743:不可重疊最長重複子串

二分答案,height分組,維護最大最小sa,判定一下。

#include#include#include#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

using namespace std;

const int n=20000+5;

int s[n],a[n],b[n],c[n],sa[n],rk[n],h[n],n,*x,*y;

int abs(int x)

void radix(int m)

void getsa(int m)

}void geth()

bool check(int k)else

} return false;

}int main()

if(l>=5)printf("%d\n",l);

else puts("0");

} return 0;

}

spoj 694&705:本質不同的子串個數

sigma(n-sa[i]+1-height[i])

#include#include#include#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

using namespace std;

const int n=1000+5;

char s[n];

int sa[n],h[n],rk[n],a[n],b[n],c[n],*x,*y,n;

void radix(int m)

void getsa(int m)

}void geth()

int main()

return 0;

}

poj 3693:重複次數最多的連續重複子串(好繞啊)

列舉長度l,計算次數,複雜度是n*調和級數(n),中間細節比較麻煩。。。。。

#include#include#include#include#include#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

using namespace std;

const int n=100000+10;

struct suffix_array

void radix(int m)

void getsa(int m)

} void geth()

void rmq_init()

void pre()

}sol;

char s[n];

int a[n];

int main()else if(ti==ans)a[++top]=l;

} int len=-1,st;

for(int i=1;i<=n&&len==-1;i++)

for(int j=1;j<=top;j++)

} printf("case %d: ",++kase);

for(int i=st,j=1;j<=len*ans;j++,i++)putchar(s[i]);

putchar('\n');

} return 0;

}

poj 2774:雙串最長公共子串

兩個串中間加個奇怪的符號然後連線起來,跑一遍字尾陣列,當sa[i]和sa[i-1]不在乙個串時的最大height[i]即為答案。

#include#include#include#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

using namespace std;

const int n=200000+10;

char s[n];

int a[n],b[n],c[n],sa[n],rk[n],h[n],n,*x,*y;

void radix(int m)

void getsa(int m)

}void geth()

int main()

poj 3415:長度不小於k的公共子串個數

繼續串接,跑一遍字尾陣列,對於每乙個a的字尾和b的字尾計算一次lcp算出答案,於是n^2**,轉用單調棧維護a的height,掃到b的時候算一下,反過來再做一次,得出總答案。

#include#include#includeusing namespace std;

typedef long long ll;

#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

const int n=200000+5;

char s[n];

int a[n],b[n],c[n],sa[n],rk[n],h[n],n,*x,*y;

void radix(int m)

void getsa(int m)

}void geth()

int st[n][2];

int main()

} tot=top=0;

for(int i=2;i<=n+1;i++)

st[top][0]=h[i];st[top++][1]=cnt;

if(sa[i]

這題其實可以kmp做我會亂說= =+(常數我吃了)。

n個串連起來,中間有奇怪的不同的字元,跑一遍字尾陣列,二分答案,height分組,每組判定一下有木有集齊(7個字尾召喚神龍?)k個不在同乙個串的字尾,集齊了就可以(召喚神龍)return true

順便說這題召喚出了我人生中的第乙個ole(我也不造怎麼回事啊,然後莫名其妙就a了)

#include#include#includeusing namespace std;

#define cmp(x) (y[sa[i]+x]==y[sa[i-1]+x])

const int n=100000+1000;

char s[n];

int a[n],b[n],c[n],sa[n],rk[n],h[n],*x,*y,n;

void radix(int m)

void getsa(int m)

}void geth()

int in[n],t,k,now[105];

bool check(int len)

else

} }if(tot>k)return true;

return false;

}int ans[n];

void print(int len)

else

} }if(tot>k)ans[++sz]=sa[n];

ans[0]=sz;

}int main()

if(flag)puts("");

flag=true;

if(l==1)puts("?");

else

void getsa(int m)

}void geth()

int in[n],mx[15],mn[15],m;

bool check(int len)

} return false;

}int main()

else r=mid-1;

} printf("%d\n",ans);

} return 0;

}

然後其實還有乙個最小迴圈節和乙個最長回文串,其實這兩個用kmp和manacher做就好了嘛,還快一點呢。

總結一下嘛,這類題無非就是 串接,二分答案,height分組,偶爾再來個單調棧什麼的,其實做法都差不多,模型很相像,理解了height陣列和sa陣列的定義啊性質啊什麼的就很好做(水)了。

好了是時候開啟字尾自動機的大門了(還是好虛啊腫麼辦)

洛谷oj 1030 水水水

題目描述 給出一棵二叉樹的中序與後序排列。求出它的先序排列。約定樹結點用不同的大寫字母表示,長度 8 輸入輸出格式 輸入格式 2行,均為大寫字母組成的字串,表示一棵二叉樹的中序與後序排列。輸出格式 1行,表示一棵二叉樹的先序。輸入輸出樣例 輸入樣例 1 badc bdca 輸出樣例 1 abcd 這...

acmoj 算路程 水水

在群裡看到這個比賽就註冊做了一道,這個真水,acmoj上的第一道題,貼上來紀念紀念,事實上是我現在做個題目就像貼上來 include include include include includeusing namespace std struct node b 10005 int a 10005 ...

水題 陣列重建

題目 陣列重建 description durong喜歡玩陣列,但是他不小心弄丟了乙個陣列的一些數字。他只知道原來陣列的元素滿足a i a i 1 1 m 1 i n 並且都大於等於0。現在的陣列中弄丟的數字用 1表示。你需要幫助durong找回丟失的元素,重建陣列。input 輸入第一行為兩個整數...