kuangbin专题十六:KMP & 扩展KMP & Manacher

HDU1711 Number Sequence

思路:kmp模板。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;
const int maxm = 1e4 + 5;
const int maxn = 1e6 + 5;
int T, n, m;

int a[maxn], b[maxm];
int Next[maxm];

void genNext(){
    Next[0] = -1;
    int j = -1;
    for(int i = 1; i < m; i++){
        while(j != -1 && b[i] != b[j+1]) j = Next[j];
        if(b[i] == b[j+1]) j++;
        Next[i] = j;
    }
}

int kmp(){
    int j = -1;
    for(int i = 0; i < n; i++){
        while(j != -1 && a[i] != b[j+1]) j = Next[j];
        if(a[i] == b[j+1]) j++;

        if(j == m-1)
            return i - m + 2;
    }
    return -1;
}

int main(){
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) scanf("%d", a+i);
        for(int i = 0; i < m; i++) scanf("%d", b+i);

        genNext();
        printf("%d\n", kmp());
    }
    return 0;
}
View Code

 

HDU1686 Oulipo

思路:kmp模板。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1e6 + 5;
const int maxm = 1e4 + 5;

char W[maxm], T[maxn];
int Next[maxm];

int Tn, n, m;

void genNext() {
    Next[0] = -1;
    int j = -1;
    for (int i = 1; i < m; i++){
        while(j != -1 && W[i] != W[j+1]) j = Next[j];
        if(W[i] == W[j+1]) j++;
        Next[i] = j;
    }
}

int kmp(){
    int j = -1, res = 0;
    for(int i = 0; i < n; i++){
        while(j != -1 && T[i] != W[j+1]) j = Next[j];
        if(T[i] == W[j+1]) j++;

        if (j == m-1)
            res++, j = Next[j];
    }
    return res;
}

int main(){
    scanf("%d", &Tn);
    while(Tn--){
        scanf("%s", W);
        scanf("%s", T);
        m = strlen(W), n = strlen(T);

        genNext();
        printf("%d\n", kmp());
    }
    return 0;
}
View Code

 

HDU2087 剪花布条

 思路:kmp模板题。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1e3 + 5;
char tile[maxn], pattern[maxn];
int Next[maxn];
int n, m;

void genNext() {
    int j = -1;
    Next[0] = -1;
    for(int i = 1; i < m; i++){
        while(j != - 1 && pattern[i] != pattern[j+1]) j = Next[j];
        if (pattern[i] == pattern[j + 1]) j++;
        Next[i] = j;
    }
}

int kmp(){
    genNext();
    int j = -1, res = 0;
    for (int i = 0; i < n; i++){
        while(j != -1 && tile[i] != pattern[j+1]) j = Next[j];
        if (tile[i] == pattern[j+1]) j++;

        if(j == m-1)
            res++, j = -1;
    }
    return res;
}

int main(){
    while(scanf("%s", tile) && tile[0] != '#'){
        scanf("%s", pattern);
        n = strlen(tile), m = strlen(pattern);

        printf("%d\n", kmp());
    }
    return 0;
}
View Code

 

HDU3746 Cyclic Nacklace

思路:题目没看,以前代码。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 1e5+5;
char T[maxn];
int tlen;
int Next[maxn];

void getNext(){
    int i=0, j=-1;
    Next[0] = -1;
    while(i < tlen){
        if(j==-1 || T[i]==T[j]) Next[++i] = ++j;
        else j = Next[j];

    }
}

int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%s", T);
        tlen = strlen(T);
        getNext();
        int length = tlen - Next[tlen];
        if(tlen != length && tlen%length==0)
            printf("0\n");
        else{
            int add = length - Next[tlen] % length;
            printf("%d\n", add);
        }
    }
    return 0;
}
View Code

 

HDU1358 Period

思路:利用next数组寻找循环子列长度。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1e6 + 5;
int n;
char s[maxn];
int Next[maxn];

void genNext(){
    int j = -1;
    Next[0] = -1;
    for(int i = 1; i < n; i++){
        while(j != -1 && s[i] != s[j+1]) j = Next[j];
        if(s[i] == s[j+1]) j++;
        Next[i] = j;
    }
}

int main(){
    int T = 0;
    while(scanf("%d", &n) && n){
        scanf("%s", s);
        genNext();

        printf("Test case #%d\n", ++T);
        for(int i = 1; i < n; i++)
            if(Next[i] >= i/2 && (i+1)%(i-Next[i])==0)
                printf("%d %d\n", i+1, (i+1)/(i-Next[i]));
        printf("\n");
    }
    return 0;
}
View Code

 

POJ2406 Power Strings

思路:同前一题。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1e6 + 5;
int n;
char s[maxn];
int Next[maxn];

void genNext(){
    int j = Next[0] = -1;
    for(int i = 1; i < n; i++){
        while(j != -1 && s[i] != s[j+1]) j = Next[j];
        if(s[i] == s[j+1]) j++;
        Next[i] = j;
    }
}

int main(){
    while(scanf("%s", s) && s[0] != '.'){
        n = strlen(s);
        genNext();

        if(n % (n-1 - Next[n-1]) == 0)
            printf("%d\n", n / (n - 1 - Next[n-1]));
        else
            printf("1\n");
    }
    return 0;
}
View Code

 

POJ2752 Seek the Name, Seek the Fame

 思路:扩展kmp。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 4e5 + 5;
int n;
char s[maxn];
int z[maxn];

void exKMP(){
    memset(z, 0, sizeof(z));
    for(int i = 1, l = 0, r = 0; i < n; i++){
        if(i <= r) z[i] = min(r - i + 1, z[i - l]);
        while(i + z[i] < n && s[i + z[i]] == s[z[i]]) z[i]++;
        if(i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
    }
}

int main(){
    while(~scanf("%s", s)){
        n = strlen(s);

        exKMP();

        for (int i = n - 1; i > 0; i--)
            if (i + z[i] == n)
                printf("%d ", z[i]);
        printf("%d\n", n);
    }
    return 0;
}
View Code

 

POJ3080 Blue Jeans

 

HDU2594 Simpsons’ Hidden Talents

思路:扩展kmp,注意最长后缀取值范围。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 2 * 50000 + 5;
char s[maxn];
int z[maxn];
int m, n;

void extkmp(){
    memset(z, 0, sizeof(z));
    for(int i = 1, l = 0, r = 0; i < m; i++){
        if(i <= r) z[i] = min(r - i + 1, z[i - l]);
        while(i + z[i] < m && s[i + z[i]] == s[z[i]]) z[i]++;
        if(i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
    }
}


int main(){
    while(~scanf("%s", s)){
        n = strlen(s);
        scanf("%s", s + n);
        m = strlen(s);
        extkmp();

        int res = 0;
        for(int i = max(n, m-n); i < m; i++){
            if(i + z[i] == m){
                res = i;
                break;
            }
        }
        if(res)
            printf("%s %d\n", s+res, m-res);
        else
            printf("0\n");
    }
    return 0;
}
View Code

 

HDU3336 Count the string

思路:莫名其妙的wa了两次。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 2e5 + 5;
const int mod = 10007;
char s[maxn];
int Next[maxn];
int dp[maxn];
int n;

void rev(){
    for(int i = 0; i < n / 2; i++){
        char t = s[i];
        s[i] = s[n-i-1];
        s[n-i-1] = t;
    }
}

void genNext(){
    memset(Next, 0, sizeof(Next));
    int j;
    j = Next[0] = -1;
    for(int i = 1; i < n; i++){
        while(j != -1 && s[i] != s[j+1]) j = Next[j];
        if(s[i] == s[j+1]) j++;
        Next[i] = j;
    }
}

int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%s", &n, s);

        genNext();

        memset(dp, 0, sizeof(dp));
        int ans = 0;
        for(int i = 0; i < n; i++){
            dp[i] = (dp[Next[i]] + 1) % mod;
            ans = (dp[i] + ans) % mod;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

HDU4300 Clairewd’s message

思路:题目太长不看。

 

HDU1238 Substrings

 

posted @ 2021-04-17 20:51  Nanachi  阅读(62)  评论(0编辑  收藏  举报