• poj 3729 Facer’s string


    Facer’s string
    Time Limit: 3000MS   Memory Limit: 65536K
    Total Submissions: 2155   Accepted: 644

    Description

    Minifacer was very happy these days because he has learned the algorithm of KMP recently. Yet his elder brother, Hugefacer, thought that Minifacer needs a deeper understanding of this algorithm. Thus Hugefacer decided to play a game with his little brother to enhance his skills.

    First, Hugefacer wrote down two strings S1 and S2. Then Minifacer tried to find a substring S3 of S1 which meets the following requirements: 1) S3 should have a length of k (which is a constant value); 2) S3 should also be the substring of S2. After several rounds, Hugefacer found that this game was too easy for his clever little brother, so he added another requirement: 3) the extended string of S3 should NOT be the substring of S2. Here the extended string of S3 is defined as S3 plus its succeed character in S1 (if S3 does not have a succeed character in S1, the extended string of S3 is S3 + ' ' which will never appear in S2). For example, let S1 be "ababc", if we select the substring from the first character to the second character as S3 (so S3 equals "ab"), its extended string should be "aba"; if we select the substring from the third character to the fourth character as S3, its extended string should be "abc"; if we select the substring from the fourth character to the fifth character as S3, its extended string should be "bc".

    Since the difficult level of the game has been greatly increased after the third requirement was added, Minifacer was not able to win the game and he thought that maybe none of the substring would meet all the requirements. In order to prove that Minifacer was wrong, Hugefacer would like to write a program to compute number of substrings that meet the three demands (Note that two strings with same appearance but different positions in original string S1 should be count twice). Since Hugefacer do not like characters, he will use non-negative integers (range from 0 to 10000) instead.

    Input

    There are multiple test cases. Each case contains three lines: the first line contains three integers nm and k where n represents the length of S1m represents the length of S2 and k represents the length of substring; the second line contains string S1 and the third line contains string S2. Here 0 ≤ nm ≤ 50000. Input ends with EOF.

    Output

    For each test case, output a number in a line stand for the total number of substrings that meet the three requirements.

    Sample Input

    5 5 2
    1 2 1 2 3
    1 2 3 4 5
    5 5 3
    1 2 1 2 3
    1 2 3 4 5
    

    Sample Output

    2
    1

    题意:有两个字符串s1,s2,现在要从s1中找到子串s3,其长度必须大于等于K,使得s3也是s2的子串,并且s3再加上s1中的一个后继字符后不再是s2的子串,问满足条件的s3的数量。
    思路:求出后缀数组和高度数组,那么对于s1中每一个后缀,判断这个后缀和s2中的任意一个后缀的lcp是否等于K。可以换个角度考虑这个问题,在lcp数组中,把数值大于等于K的连续的几个后缀的lcp当成一块来考虑,
    如果这个块中s1,s2中的后缀都有,说明这些后缀当中的任意两个后缀的lcp都是大于等于K的,这样把lcp数组分成一块一块来考虑就能很快求出A中所有后缀和B中后缀的lcp大于等于K的数量,正好等于K的数量就是
    sum(K)-sum(K+1)
    AC代码:
    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    #include<string>
    #include<cmath>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int N_MAX = 50000 + 20;
    typedef long long ll;
    int n, N,M, k, K;
    int Rank[N_MAX * 2];
    int tmp[N_MAX * 2];
    int sa[N_MAX * 2];
    int lcp[N_MAX * 2];
    int s[N_MAX * 2];
    bool compare_sa(const int& i, const int& j) {
        if (Rank[i] != Rank[j])return Rank[i] < Rank[j];
        else {
            int ri = i + k <= n  ? Rank[i + k] : -1;
            int rj = j + k <= n ? Rank[j + k] : -1;
            return ri < rj;
        }
    }
    
    void construct_sa(const int *S, int *sa) {
        for (int i = 0; i <= n; i++) {
            sa[i] = i;
            Rank[i] = i < n ? S[i] : -1;
        }
        for (k = 1; k <= n; k *= 2) {
            sort(sa, sa + n + 1, compare_sa);
            tmp[sa[0]] = 0;
            for (int i = 1; i <= n; i++) {
                tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
            }
            for (int i = 0; i <= n; i++) {
                Rank[i] = tmp[i];
            }
        }
    }
    void construct_lcp(const int *S, int *sa, int *lcp) {
        memset(lcp, 0, sizeof(lcp));
        for (int i = 0; i <= n; i++)Rank[sa[i]] = i;
        int h = 0;
        lcp[0] = 0;
        for (int i = 0; i < n; i++) {
            int j = sa[Rank[i] - 1];
            if (h > 0)h--;
            for (; j + h < n&&i + h < n; h++) {
                if (S[j + h] != S[i + h])break;
            }
            lcp[Rank[i] - 1] = h;
        }
    }
    
    
    ll find_num(int K) {
        int A = 0, B = 0;
        ll res = 0;
        for (int i = 0; i < n;i++) {
            if (lcp[i] < K) {
                if (B > 0)res += A;
                A = 0; B = 0;
            }    
            if (sa[i + 1] < N)A++;
            if (sa[i + 1] > N) B++;
        }
        return res;
    }
    
    int main() {
        while (scanf("%d%d%d", &N, &M, &K) != EOF) {
            for (int i = 0; i < N; i++) {
                scanf("%d", &s[i]);
                s[i]++;
            }
            s[N] = '$';
            for (int i = N + 1; i < N + M + 1; i++) {
                scanf("%d", &s[i]);
                s[i]++;
            }
            n = N + M + 1;
            s[n] = 0;
            construct_sa(s, sa);
            construct_lcp(s, sa, lcp);
            printf("%lld
    ",find_num(K)-find_num(K+1));
        }
        return 0;
    }
  • 相关阅读:
    开源软件、自由软件及免费软件的区别 2015-04-13 22:50 45人阅读 评论(0) 收藏
    Linux中fork()函数详解 2015-04-13 22:48 30人阅读 评论(0) 收藏
    ubuntu系统文件夹目录说明 分类: Ubuntu学习笔记 2015-04-13 21:21 49人阅读 评论(0) 收藏
    gdb使用笔记 2015-04-11 19:55 32人阅读 评论(0) 收藏
    Vim 使用笔记 2015-04-10 19:50 51人阅读 评论(0) 收藏
    access_ok()
    linux内核驱动中_IO, _IOR, _IOW, _IOWR 宏的用法与解析(引用)
    编译andriod源码出错:java.lang.UnsupportedClassVersionError: com/google/doclava/Doclava : Unsupported
    Linux内核树的建立-基于ubuntu系统
    sysfs接口整理
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/9071773.html
Copyright © 2020-2023  润新知