• hdu 1867 A + B for you again


    Generally speaking, there are a lot of problems about strings processing. Now you encounter another such problem. If you get two strings, such as “asdf” and “sdfg”, the result of the addition between them is “asdfg”, for “sdf” is the tail substring of “asdf” and the head substring of the “sdfg” . However, the result comes as “asdfghjk”, when you have to add “asdf” and “ghjk” and guarantee the shortest string first, then the minimum lexicographic second, the same rules for other additions.

    InputFor each case, there are two strings (the chars selected just form ‘a’ to ‘z’) for you, and each length of theirs won’t exceed 10^5 and won’t be empty.OutputPrint the ultimate string by the book.Sample Input
    asdf sdfg
    asdf ghjk
    Sample Output
    asdfg
    asdfghjk

    合并字符串,两串a,b,a的后缀和b的前缀最大匹配长度为d,b的后缀和a的前缀的最大匹配长度为e,哪个长度大,就怎么衔接,否则按字母顺序衔接。
    kmp找两个长度。
    代码:
    #include <stdio.h>
    #include <string.h>
    #define MAX 100005
    char a[MAX],b[MAX];
    int Next[MAX];
    void getNext(int n,char *s) {
        int i = 0,j = -1;
        Next[i] = -1;
        while(i < n) {
            if(j == -1 || s[j] == s[i]) {
                Next[++ i] = ++ j;
            }
            else j = Next[j];
        }
    }
    int kmp(char *p,char *q) {
        int n = strlen(p),m = strlen(q);
        getNext(m,q);
        int i = -1,j = -1;
        while(i < n) {
            if(j == -1 || p[i] == q[j]) {
                i ++;j ++;
            }
            else j = Next[j];
        }
        return j;
    }
    int main() {
        while(~scanf("%s%s",a,b)) {
            int d = kmp(a,b),e = kmp(b,a);///保存a后缀和b前缀的最大重叠 以及 反过来 比较哪个大 就重叠那个 按相应顺序输出,如果相等就按字典序
            if(d > e) printf("%s%s",a,b + d);
            else if(d < e) printf("%s%s",b,a + e);
            else {
                if(strcmp(a,b) > 0)printf("%s%s",b,a + e);
                else printf("%s%s",a,b + d);
            }
            putchar('
    ');
        }
    }

    也可以组合求Next。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAX 100005
    using namespace std;
    char a[MAX],b[MAX],s[MAX * 2];
    int Next[MAX * 2],m;
    int getNext(char *p,char *q) {
        strcpy(s,p);
        strcat(s,q);
        int i = 0,j = -1;
        Next[i] = -1;
        while(s[i]) {
            if(j == -1 || s[j] == s[i]) {
                Next[++ i] = ++ j;
            }
            else j = Next[j];
        }
        int  c = strlen(s);
        while(Next[c] > m) c = Next[c];
        return Next[c];
    }
    int main() {
        while(~scanf("%s%s",a,b)) {
            m = min(strlen(a),strlen(b));
            int d = getNext(b,a),e = getNext(a,b);///保存a后缀和b前缀的最大重叠 以及 反过来 比较哪个大 就重叠那个 按相应顺序输出,如果相等就按字典序
            if(d > e) printf("%s%s",a,b + d);
            else if(d < e) printf("%s%s",b,a + e);
            else {
                if(strcmp(a,b) > 0)printf("%s%s",b,a + e);
                else printf("%s%s",a,b + d);
            }
            putchar('
    ');
        }
    }

    当然 也可以用扩展kmp

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAX 100005
    using namespace std;
    char a[MAX],b[MAX];
    int Next[MAX],Prefix[MAX];
    void getNext(char *str) {///获得Next数组
        int p = 1;///匹配最远的开始匹配位置 比如从i开始和0位置依次往后匹配相等能到最远的位置 p就是i 即i + Next[i] - 1最大时的i为p
        Next[0] = strlen(str);///显然自己和自己匹配
        Next[1] = 0;
        while(str[Next[1] + 1] && str[Next[1] + 1] == str[Next[1]]) Next[1] ++;///匹配1位置作为基础
        for(int i = 2;str[i];i ++) {///2位置开始
            if(i + Next[i - p] < p + Next[p]) Next[i] = Next[i - p];///如果不超过最远位置
            else {///超过最远位置
                if(p + Next[p] - 1 >= i) Next[i] = p + Next[p] - i;///i点没超过最远位置 实际是 p + Next[p] - 1 - i + 1
                else Next[i] = 0;///否则从头开始匹配啊
                while(str[Next[i] + i] && str[Next[i]] == str[Next[i] + i]) Next[i] ++;///继续匹配
                p = i;
            }
        }
    }
    int ExKmp(char *str1,char *str2) {
        getNext(str2);
        int p = 0,len = strlen(str1);
        Prefix[0] = 0;
        while(str1[Prefix[0]] && str2[Prefix[0]] && str1[Prefix[0]] == str2[Prefix[0]]) Prefix[0] ++;
        for(int i = 1;str1[i];i ++) {
            if(i + Next[i - p] < p + Prefix[p]) Prefix[i] = Next[i - p];///i加上i-p前缀长度 没超过最远位置
            else {
                if(i <= p + Prefix[p] - 1) Prefix[i] = p + Prefix[p] - i;///i没超过最远位置
                else Prefix[i] = 0;
                while(str1[i + Prefix[i]] && str1[i + Prefix[i]] == str2[Prefix[i]]) Prefix[i] ++;///继续匹配
                p = i;///更新最远位置下标
            }
        }
        for(int i = 0;i < len;i ++) {
            if(i + Prefix[i] == len) return Prefix[i];
        }
        return 0;
    }
    int main() {
        while(~scanf("%s%s",a,b)) {
            int d = ExKmp(a,b),e = ExKmp(b,a);///保存a后缀和b前缀的最大重叠 以及 反过来 比较哪个大 就重叠那个 按相应顺序输出,如果相等就按字典序
            if(d > e) printf("%s%s",a,b + d);
            else if(d < e) printf("%s%s",b,a + e);
            else {
                if(strcmp(a,b) > 0)printf("%s%s",b,a + e);
                else printf("%s%s",a,b + d);
            }
            putchar('
    ');
        }
    }

     再次复习扩展kmp

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAX 100005
    using namespace std;
    
    void getNext(char *str,int *Next) {
        int p = 1;
        while(str[1 + Next[1]] && str[1 + Next[1]] == str[Next[1]]) Next[1] ++;
        for(int i = 2;str[i];i ++) {
            if(i + Next[i - p] < p + Next[p]) Next[i] = Next[i - p];
            else {
                if(i <= p + Next[p] - 1) Next[i] = p + Next[p] - i;
                else Next[i] = 0;
                while(str[i + Next[i]] && str[i + Next[i]] == str[Next[i]]) Next[i] ++;
                p = i;
            }
        }
    }
    int ExKmp(char *s,char *t) {
        int Next[MAX] = {0},Prefix[MAX] = {0};
        getNext(t,Next);
        int p = 0;
        while(s[0 + Prefix[0]] && s[0 + Prefix[0]] == t[Prefix[0]]) Prefix[0] ++;
        for(int i = 1;s[i];i ++) {
            if(i + Next[i - p] < p + Prefix[p]) Prefix[i] = Next[i - p];
            else {
                if(i < p + Prefix[p]) Prefix[i] = p + Prefix[p] - i;
                else Prefix[i] = 0;
                while(s[i + Prefix[i]] && s[i + Prefix[i]] == t[Prefix[i]]) Prefix[i] ++;
                if(i + Prefix[i] > p + Prefix[p]) p = i;///不加这一步 最后返回的就不对,  比如 aaaa aaa 应输出 aaaa
            }
        }
        return p + Prefix[p] < strlen(s) ? 0 : Prefix[p];
    }
    int main() {
        char a[MAX],b[MAX];
        while(~scanf("%s%s",a,b)) {
            int d = ExKmp(a,b),e = ExKmp(b,a);
            if(d > e) printf("%s%s",a,b + d);
            else if(d < e) printf("%s%s",b,a + e);
            else {
                if(strcmp(a,b) > 0)printf("%s%s",b,a + e);
                else printf("%s%s",a,b + d);
            }
            putchar('
    ');
        }
    }
  • 相关阅读:
    Silverlight DataGrid 获取 Row 左键双击事件
    数据结果集拼接到一行
    程序“[6040] iisexpress.exe”已退出,返回值为 0 (0x0)。
    新手用WPF山寨QQ管家7.6(二)
    风向十六方位图和温度湿度图
    新手向使用XAML画出Win8风格图标的照相机,小姐你相机~~
    新手用WPF山寨QQ管家7.6(一)
    实验一
    实验5
    实验4
  • 原文地址:https://www.cnblogs.com/8023spz/p/7795862.html
Copyright © 2020-2023  润新知