• FZU 2128 最长子串


    题目链接:最长子串 

    思路:依次找出每个子串的在字符串中的首尾地址,所有子串先按照尾地址从小到大排序。然后首地址从小到大排。

    遍历一遍每个子串的首地址和它后面相邻子串的尾地址之差-1, 第一个子串的首地址,字符串长度-最后一个子串的首地址-1的最大值就是ans。

    st1----------ed1

    -------st2------------ed2

    例如这种情况说明,可能出现的一个ans 就是 ed2和st1之间的字符个数。这时候没有ed2最后一个字符,st1第一个字符,所以不包含str1和str2.

    关于找每个子串的位置,有两种方法,kmp和strstr.

    会找到多少个子串位置呢,最大当然不是n,而是字符串长度!结构体数组开小,RE了一个半点~~~

    kmp AC 代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 1000005;
    
    struct Node {
    	int st, ed;
    } node[maxn];
    
    char s[maxn], t[1005][105];
    int n, cnt, next[105];
    
    bool cmp(Node a, Node b) {
        if (a.ed != b.ed)
        return a.ed < b.ed;
        else return a.st <= b.st;
    }
    
    void get_next(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]) {
                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;
        get_next(p);
    
        while(i<lens && j<lenp) {
            if (j == -1 || s[i] == p[j]) {
                i++;
                j++;
            }
            else j = next[j];
           if (j == lenp) {
                node[cnt].st = i-lenp;
                node[cnt].ed = i-1;
                cnt++;
                j = next[j];
            }
        }
    }
    
    
    int main() {
    	while (scanf("%s", s) == 1) {
    		scanf("%d", &n);
    		for (int i = 0; i < n; i++)
    			scanf("%s", t[i]);
    		cnt = 0;
    		for (int i = 0; i < n; i++) {
    			kmp(s, t[i]);
    		}
    		sort(node, node + cnt, cmp);
    		int ans = -1;
    		for (int i=0; i<cnt-1; ++i) {
                int st = node[i].st;
                int ed = node[i+1].ed;
                ans = max(ans, ed - st - 1);
            }
    
            int len = strlen(s);
            if (cnt > 0) {
                ans = max(ans, node[0].ed);
                ans = max(ans, len-node[cnt-1].st-1);
            }
            else ans = len;
            printf("%d
    ", ans);
    	}
    }
    

      

    strstr函数处理AC代码:

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    char s[1000010], p[110];
    char str[1000010];
    
    struct Node {
        int st, ed;
    }node[1000010];
    
    int next[110];
    int cnt;
    
    bool cmp(Node a, Node b) {
        if (a.ed != b.ed)
        return a.ed < b.ed;
        else return a.st <= b.st;
    }
    
    bool check(char s[], char p[]) {
        if (strstr(s, p))
            return true;
        return false;
    }
    
    void solve(char s[], char p[], int pre) { // 开始没设pre 参数。这样每次找到的位置只是相对当前字符串的,不能直接设为node[cnt].st 和 node[cnt].ed.
        int lenp = strlen(p);
        if (check(s, p)) {
            int num = strstr(s, p) - s;
            node[cnt].st = num + pre;
            node[cnt].ed = num + pre + lenp - 1;
            cnt++;
            solve(s+num+lenp, p, pre+num+lenp);
        }
    }
    
    int main() {
        int n;
        while(~scanf("%s", s)) {
            cnt = 0;
            scanf("%d", &n);
            for (int i=0; i<n; ++i) {
                scanf("%s", p);
                solve(s, p, 0);
            }
            sort(node, node+cnt, cmp);
            int ans = 0;
    
            for (int i=0; i<cnt-1; ++i) {
                int st = node[i].st;
                int ed = node[i+1].ed;
                ans = max(ans, ed - st - 1);
            }
            int len = strlen(s);
            if (cnt > 0) {
                ans = max(ans, node[0].ed);
                ans = max(ans, len-node[cnt-1].st-1);
            }
            else ans = len;
            printf("%d
    ", ans);
        }
        return 0;
    }
    

      

    后话,感觉无论是kmp还是strstr都明显会超时,如kmp是 n*strlen(str),最大是10^3*10^6。然,并没有,而且题解貌似都是这样的解........

    挺好的题,会的kmp,需要思考的方案。

  • 相关阅读:
    你是一直认为 count(1) 比 count(*) 效率高么?
    php 判断是不是https链接
    php 版本比较
    php 执行效率
    redis 队列缓存 + mysql 批量入库 + php 离线整合
    php 高并发下数据同步的问题
    一个合格的工程师的知识结构
    php 代码编写的格式
    php 四种基础算法 ---- 快速排序法
    php 四种基础算法 ---- 插入排序法
  • 原文地址:https://www.cnblogs.com/icode-girl/p/5347651.html
Copyright © 2020-2023  润新知