1、KMP算法
给出主串和模式串,求模式串在主串的位置
class Mystring {
string s;
int len;
int* next;
public:
Mystring(string s = "") {
this->s = s;
this->len = s.size();
next = new int[len + 1];
get_next();
}
// 构造next数组
void get_next() {
int i = 0;
next[0] = -1;
int j = -1;
while (i < len - 1) {
if (j == -1 || s[i] == s[j]) {
++i, ++j;
next[i] = j;
}
else j = next[j];
}
}
// KMP算法:在所给主串mains,查找模式串s是否在mains中,若在,则返回所在位置开头下标
int KMP(string mains, int pos) {
int i = pos, j = 0;
while (i < mains.size() && j < len) {
if (j == -1 || mains[i] == s[j]) {
++i, ++j;
}
else j = next[j];
}
if (j > len-1) return i - len ;
else return -1;
}
// 展示next数组
void show_next() {
for (int i = 0; i < len; i++) {
cout << next[i] << " ";
}
cout << endl;
}
};
2、后缀数组求最长重复子串
求串的最长重复子串长度。例如:abcaefabcabc的最长重复子串是串abca,长度为4。
// 后缀数组求最长重复子串,若存在最长重复子串,则返回其长度
int work(string str) {
vector<string> s; // 后缀数组
for (int i = 0; i < str.size(); i++) {
s.push_back(str.substr(i));
}
sort(s.begin(), s.end()); // 排序
int maxlen = 0;
for (int i = 0; i < str.size() - 1; i++) {
for (int j = 1; j <= s[i].size() && j <= s[i + 1].size(); j++) {
if (s[i].substr(0,j) == s[i + 1].substr(0,j)) {
if (j > maxlen) {
maxlen = j;
}
}
else break;
}
}
if (maxlen != 0)
return maxlen;
else return -1;
}
3、求最长公共子序列
子序列在原序列中不一定连续,但在两个原序列中顺序相同,字符相同
char s1[1010],s2[1010];
int f[1010][1010];
scanf("%s",1+s1);
int lens=strlen(1+s1);
for(int i=1;i<=lens;i++) s2[lens-i+1]=s1[i];//翻转
for(int i=1;i<=lens;i++) f[i][1]=f[1][i]=0;//初始化
for(int i=1;i<=lens;i++)//模板
for(int j=1;j<=lens;j++)
if(s1[i]!=s2[j]) f[i][j]=max(f[i-1][j],f[i][j-1]);
else f[i][j]=f[i-1][j-1]+1;
cout << f[lens][lens];//输出
一个序列和其颠倒序列求最长公共子序列,则可以得到该序列最长回文子序列