• pku 2541


    题意:

    在文本T[1..n],找一个最长的后缀(长度为m,m<=13),以这个后缀为匹配的模式P:T[n-m+1..n]

    找出P在文本T[1..n-1]出现的最后一个起始位置k,(k<=n-m)

    若找到k,则得出T[n+1]为找到的模式T[k..k+m-1]的下一个位置: :T[n+1] = T[k+m]

    如果m==13时找不到,则尝试m==12直到m==1,

    如果都找不到,T[n+1] = 0;

    分析:

    * KMP
    * 一旦得到一个匹配之后就增加源串长度 下次找匹配 T 和 P 都会变

    * 因为这次匹配之后 给源串增加的那个字符就是前面相匹配的串的下一个字符
    * 所以至少这个位置会继续匹配下去
    * 但是要求最右面的 长度又不大于 13 所以可能新构成的 P 在那个位置之后还有匹配

    * ???
    * 没有用新的 P 去找更右面的匹配 而是找到一个之后就确定输出解
    */

    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int maxm = 14;
    const int maxl = 1000;
    const int maxn = 1000001;
    
    int m, n , s;
    char T[maxn+maxl], P[maxm];
    int nxt[maxm];
    
    int KMP(const char*  T, const char* P)
    {
        nxt[0] = -1;
        int k = -1;
        for(int q=1;q<=m-1;q++){
            while (k > -1 && P[k+1] != P[q])
                k = nxt[k];
            if (P[k+1] == P[q]) ++k;
            nxt[q] = k;
        }
        int pos = -1;
        int j = -1;
        while (s < n) {
            while (j > -1 && P[j+1] != T[s])
                j = nxt[j];
            if (P[j+1] == T[s]) ++j;
            if (j+1 == m) {
                pos = s + 1 - m;
                j = nxt[j];//题目要求找最右边的K,所以还要继续往右找
            }
            ++s;
        }
        s = pos;
        return pos;
    }
    int main()
    {
        int N, L;
        scanf("%d %d\n", &N, &L);
        gets(T);
    	s=0;
        for(int i=0;i<L;i++)
    	{
            n = N - 1;
            bool find = false;
            for(int t=13;t>=1;t--)
    			if (t < N) {
                m = t;
                memcpy(P, T+N-m, m);
                P[m] = '\0';
                int pos = KMP(T, P);
                if (pos != -1) {
                    printf("%c", T[N++] = T[pos+m]);
                    find = true;
                    break;
                }
            }
            if (!find) printf("%c", T[N++] = '0');
        }
        printf("\n");
        return 0;
    } 
    
  • 相关阅读:
    写代码实现两个 goroutine,其中一个产生随机数并写入到 go channel 中,另外一 个从 channel 中读取数字并打印到标准输出。最终输出五个随机数。
    05| RWMutex:读写锁的实现原理及避坑指南
    go 面试题
    go 局部变量在哪
    12 _ atomic:要保证原子操作,一定要使用这几种方法
    11 _ Context:信息穿透上下文
    什么是线程
    go面试题
    redis连接池 go
    docker 指定版本rpm包安装
  • 原文地址:https://www.cnblogs.com/nanke/p/2242576.html
Copyright © 2020-2023  润新知