根據羅的**,兩個串的中間要加乙個ascii碼比任何字母都小的字元
最長公共子串(pku2774,ural1517)
給定兩個字串a 和b,求最長公共子串。
演算法分析:
字串的任何乙個子串都是這個字串的某個字尾的字首。求a 和b 的最長公共子串等價於求a 的字尾和b 的字尾的最長公共字首的最大值。如果列舉a和b 的所有的字尾,那麼這樣做顯然效率低下。由於要計算a 的字尾和b 的字尾的最長公共字首,所以先將第二個字串寫在第乙個字串後面,中間用乙個沒有出現過的字元隔開,再求這個新的字串的字尾陣列。觀察一下,看看能不能從這個新的字串的字尾陣列中找到一些規律。以a=「aaaba」,b=「abaa」為例,如圖 所示。
那麼是不是所有的height 值中的最大值就是答案呢?不一定!有可能這兩個字尾是在同乙個字串中的, 所以實際上只有當suffix(sa[i-1]) 和suffix(sa[i])不是同乙個字串中的兩個字尾時,height[i]才是滿足條件的。而這其中的最大值就是答案。記字串a 和字串b 的長度分別為|a|和|b|。求新的字串的字尾陣列和height 陣列的時間是o(|a|+|b|),然後求排名相鄰但原來不在同乙個字串中的兩個字尾的height 值的最大值, 時間也是o(|a|+|b|),所以整個做法的時間複雜度為o(|a|+|b|)。時間複雜度已經取到下限,由此看出,這是乙個非常優秀的演算法。
#define maxn 211111
int wa[maxn],wb[maxn],wv[maxn],wss[maxn];//**模板的ws竟然跟g++裡的關鍵字衝突!
int r[maxn],sa[maxn];
int cmp(int *r,int a,int b,int l)
/*【倍增演算法o(nlgn)】待排序的字串放在r 陣列中,從r[0]到r[n-1],長度為n,且最大值小於m
使用倍增演算法前,需要保證r陣列的值均大於0。然後要在原字串後新增乙個0號字元
所以,若原串的長度為n,則實際要進行字尾陣列構建的r陣列的長度應該為n+1.所以呼叫da函式時,對應的n應為n+1.
*/void da(int *r,int *sa,int n,int m)
return(height[askrmq(a+1,b)]);
}char a[maxn],b[maxn];
int main()
}printf("%d\n",res);
}return 0;
}
POJ 2217 字尾陣列 最長公共子串
題目鏈結 題目大意 求兩個串的最長公共子串,注意子串是連續的,而子串行可以不連續。解題思路 字尾陣列解法是這類問題的模板解法。對於n個串的最長公共子串,這要把這些串連在一起,中間用 這類的特殊符號分隔一下。先求字尾陣列,再求最長公共字首,取相鄰兩個且屬於不同串的sa的最大lcp即可。原理就是 這樣把...
求最長公共子串
參考 最長公共子串 longest common substirng 和最長公共子串行 longest common subsequence,lcs 的區別為 子串是串的乙個連續的部分,子串行則是從不改變序列的順序,而從序列中去掉任意的元素而獲得新的序列 也就是說,子串中字元的位置必須是連續的,子串...
求最長公共子串
題目描述 給定乙個query和乙個text,均由小寫字母組成。要求在text中找出以同樣的順序連續出現在query中的最長連續字母序列的長度。例如,query為 acbac text為 acaccbabb 那麼text中的 cba 為最長的連續出現在query中的字母序列,因此,返回結果應該為其長度...