串学习笔记

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];//输出

应用:[蓝桥杯 2016 省 A] 密码脱落 - 洛谷

 一个序列和其颠倒序列求最长公共子序列,则可以得到该序列最长回文子序列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值