Vjudge19.12.21 kmp+ekmp

e-KMP专题
(1)KMP和e-KMP会用
(2) 循环节
主要还是要会转换问题,问题的转换是不难的。
KMP 求S和T匹配的个数

int nextt[maxn];
void getNext(char T[]) {
    int len=strlen(T);
    int i = 1;
    nextt[1] = 0;
    int j = 0;
    while (i < len) {
        if (j == 0 || T[i] == T[j]) {
            ++i; ++j;
            nextt[i] = j;
        } else {
            j = nextt[j];
        }
    }
}

int KMP(char S[], char T[], int next[], int pos) {
    //求T在S中pos位置后的位置
    int i = pos;
    int j= 1;
    while ( i <= S.length() && j <= T.length()) {
        if(j == 0 || S[i] == T[j]) {
            ++i;++j;
        } else {
            j = next[j];
        }
    }
    if(j > T.length())
        return i - T.length();
    else
        return 0;
}

e-KMP可以一次性求出T对S的从每位开始比较的相同的个数,保存在extend里面

struct e_KMP {
    int Next[maxn], extend[maxn];
    char *S, *T;
    int lenS, lenT;

    void init(char* S, char* T, int len1,int len2) {//第一个是被匹配的, 第二个是匹配的 
        this->S = S, this->T = T;
        lenS = len1 , lenT=len2;
    }

    void get_next() {//求模式串的next[] ta开始和从0开始时匹配的长度 
        Next[0] = lenT;//i=0的时候必然是这个 
        Next[1] = 0;
        while (Next[1] + 1 < lenT && T[Next[1]] == T[Next[1] + 1])
            Next[1]++;//单独求i=1的时候 
        int k = 1, p = Next[1];//匹配的最远位置p与对应的起始点k 
        for (int i = 2; i < lenT; i++) {
            if (p > i + Next[i - k] - 1) Next[i] = Next[i - k];
            else {
                Next[i] = max(0, p - i + 1);
                while (i + Next[i] < lenT && T[i + Next[i]] == T[Next[i]]) Next[i]++;
                k = i, p = i + Next[i] - 1;
            }
        }
    }

    void work() {//从i开始时匹配的长度 
        get_next();extend[0] = 0;//单独求第一个 
        while (extend[0] < lenS && extend[0] < lenT && S[extend[0]] == T[extend[0]])
            extend[0]++;
        int k = 0, p = extend[0] - 1;
        for (int i = 1; i < lenS; i++) {
            if (p > i + Next[i - k] - 1) extend[i] = Next[i - k];
            else {//从p-i+1开始继续往后匹配 
                extend[i] = max(0, p - i + 1);
                while (i + extend[i] < lenS && extend[i] < lenT
                    && S[i + extend[i]] == T[extend[i]])
                    extend[i]++;
                k = i, p = i + extend[i] - 1;
            }
        }
    }
}ekmp;

主要就是要会用e-KMP,即将问题转换成字符串匹配的问题

--------------------
A 转换简单

B 转换简单

C 转换简单,就是难看懂题目

D e-KMP判断回文,即用str和str的逆序匹配

E KMP找循环节,e-KMP比较大小
好坑啊这题,超过了1e5,还会显示TLE, 绝了
KMP循环节: **i%(i-next(i))==0 , 说明字符串循环到 i-1 结束
循环节长度为: i - next[i]
循环次数为: i / ( i - next[i] )

F 转换简单

G KMP循环节

H 转换简单

扫描二维码关注公众号,回复: 9476916 查看本文章

猜你喜欢

转载自www.cnblogs.com/amitherblogs/p/12381561.html
kmp