字尾陣列(sort版)
阿新 • • 發佈:2019-01-11
以下內容均取自挑戰程式設計競賽
目錄
1.字尾陣列的計算:
int n,k; int rankk[maxn+1]; int tmp[maxn+1]; //sa[i]表示排在第i的字串起始字母的下標。 //rank[i]表示從第i位字母開始的字尾排在第幾。 bool compare_sa(int i,int j){ if(rankk[i]!=rankk[j]){ return rankk[i]<rankk[j]; }else{ int ri=i+k<=n?rankk[i+k]:-1; int rj=j+k<=n?rankk[j+k]:-1; return ri<rj; } } void construct_sa(string s,int *sa){ n=s.size(); for(int i=0;i<=n;i++){ sa[i]=i; rankk[i]=i<n?s[i]:-1; } for(k=1;k<=n;k<<=1){ sort(sa,sa+n+1,compare_sa); tmp[sa[0]]=0; for(int i=1;i<=n;i++){ tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0); } for(int i=0;i<=n;i++){ rankk[i]=tmp[i]; } } }
2.基於字尾陣列的字串匹配:
KMP複雜度為,字尾陣列為,所以在比較大時,字尾陣列更高效,同時對同一個字串多次匹配時,字尾陣列更高效。
bool contain(string s,int *sa,string t){ int a=0,b=s.size(); while(b-a>1){ int c=(a+b)>>1; if(s.compare(sa[c],t.size(),t)<0) a=c; else b=c; } return s.compare(sa[b],t.length(),t)==0; }
3.高度陣列(LCP Array)
表示字尾和字尾的最長公共字首的長度位
void construct_lcp(string s,int *sa,int *lcp){ int n=s.size(); for(int i=0;i<=n;i++){ rankk[sa[i]]=i; } int h=0; lcp[0]=0; for(int i=0;i<n;i++){ int j=sa[rankk[i]-1]; if(h) h--; for(;j+h<n&&i+h<n;h++){ if(s[j+h]!=s[i+h]) break; } lcp[rankk[i]-1]=h; } }
將rmq(區間查詢)與字尾陣列結合,可以計算任意兩個字尾的最長公共字首。
字尾的公共字首長度為
4.應用
1).字串匹配
2).計算最長公共子串。例題
3).計算最長迴文子串。例題