FZU 2122 又见LKity

Posted 小小八

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FZU 2122 又见LKity相关的知识,希望对你有一定的参考价值。

题目链接又见LKity

...真是不知道怎么被这个水题卡这么久的,开始用kmp,就是过不了,无脑dbug未果。换了一种kmp模板结果就过了。确实这个模板更好理解一些吧。

然后暴力0ms过的不知道什么鬼。

正解kmp一次求出每个字串的位置,代码:

AC版:

 

/*
已 AC
*/

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

char s1[210], s2[210], s3[150010];
int next[210];

void getnext(char p[]) {
    memset(next, 0, sizeof(next));
    int len = strlen(p);
    int i = 0;
    next[0] = -1;
    int k = -1;
    while(i<len) {
        if (k == -1 || p[i] == p[k] || p[i] + 32 == p[k] || p[i] == p[k] + 32) {
            i++;
            k++;
            next[i] = k;
        }
        else k = next[k];
    }
}

void kmp(char s[], char p[]) {
    int lens = strlen(s);
    int lenp = strlen(p);
    int i = 0, j = 0;
    while(i<lens && j<lenp) {
        if (j == -1 || s[i] == p[j] || s[i] + 32 == p[j] || s[i] == p[j] + 32) {
            i++;
            j++;
        }
        else j = next[j];
        if (j == lenp) { // 说明p[0]到p[len-1]已经匹配成功 s[i-lenp] ... s[i-1] 和 P[0] ... p[lenp-1] 匹配。
            for (int k=i-lenp; k<i; ++k) {
                s[k] = ‘~‘;
            }
            j = next[j];
        }
    }
}


int main() {
    while(~scanf("%[^\n]", s1)) {
        getchar();
        scanf("%[^\n]", s2);
        getchar();
        scanf("%[^\n]", s3);
        getchar();

        int len1 = strlen(s1);
        int len2 = strlen(s2);
        int len3 = strlen(s3);

        getnext(s1);
        kmp(s3, s1);

        //cout << s1 << "===\n" << s2 << "===\n" << s3 << "===\n";
        for (int i=0; i<len3; ++i) {
            if (s3[i] == ‘~‘) {
                printf("%s", s2);
                i += len1 - 1;
            }
            else printf("%c", s3[i]);
        }
        printf("\n");
    }
    return 0;
}

 

莫名WA版:

/*
WA
*/

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <cmath>
using namespace std;

char s1[210], s2[210], s3[150010];
int next[210];

void getnext(char p[]) {
    memset(next, 0, sizeof(next));
    int len = strlen(p+1);
    next[1] = 0;
    for (int k=0, q=2; q<=len; ++q) {
        while(k>0 && abs(p[k+1]-p[q]) != 32 && p[k+1] != p[q])
            k = next[k];
        if (p[k+1] == p[q] || abs(p[k+1]-p[q]) == 32 || k==0)
            k++;
        next[q] = k;
    }
}


bool check(char temp) {
    if (temp >= ‘A‘ && temp <= ‘Z‘)
        return true;
    if (temp >= ‘a‘ && temp <= ‘z‘)
        return true;
    return false;
}

void kmp(char T[], char P[]) {
    int lenp = strlen(P+1);
    int lent = strlen(T+1);
    getnext(P);

    for (int i=1, q=0; i<=lent; ++i) {
        while(q>0 && !(P[q+1] == T[i] || (check(T[i]) && abs(P[q+1]-T[i]) == 32)))
            q = next[q];
        if (P[q+1] == T[i] || (check(T[i]) && abs(P[q+1]-T[i]) == 32))
            q++;
        if (q == lenp) {
            for (int j=i-lenp+1; j<=i; ++j)
                T[j] = ‘~‘;
            q = next[q];
            i = i + lenp - 1;
        }
    }
}

int main() {
    while(~scanf("%[^\n]", s1+1)) {
        getchar();
        scanf("%[^\n]", s2+1);
        getchar();
        scanf("%[^\n]", s3+1);
        getchar();

        kmp(s3, s1);
        int len1 = strlen(s1+1);
        int len2 = strlen(s2+1);
        int len3 = strlen(s3+1);
        for (int i=1; i<=len3; ++i) {
            if (s3[i] == ‘~‘) {
                for (int j=1; j<=len2; ++j) {
                    printf("%c", s2[j]);
                }
                i = i + len1 - 1;
            }
            else printf("%c", s3[i]);
        }
        printf("\n");
    }
    return 0;
}

暴力版:

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

char s1[210], s2[210], s3[210];

int main() {
    while(~scanf("%[^\n]", s1)) {
        getchar();
        scanf("%[^\n]", s2);
        getchar();
        scanf("%[^\n]", s3);
        getchar();

        int len1 = strlen(s1);
        int len2 = strlen(s2);
        int len3 = strlen(s3);

        for (int i=0; i<len3; ++i) {
            bool ok= true;
            for (int j=0; j<len1; ++j) {
                if (s3[i+j] != s1[j] && s3[i+j] + 32 != s1[j] && s3[i+j] != s1[j] + 32) {
                    ok = false;
                    break;
                }
            }

            if (ok) {
                i += len1 - 1;
                printf("%s", s2);
            }
            else printf("%c", s3[i]);
        }

        printf("\n");
    }
    return 0;
}

希望不会再浪费这么多时间做无用功!

 

以上是关于FZU 2122 又见LKity的主要内容,如果未能解决你的问题,请参考以下文章

FZU 2122——又见LKity——————字符串匹配暴力

FZU 2122 ——又见LKity——————KMP字符串匹配

FZU 2122 又见LKity字符串/正难则反/KMP/把一个字符串中某个部分替换为另一个部分

Android - 如何录制简单的声音片段?

又见Struts

HDU 2504 又见GCD (最大公因数+暴力)